2

J'ai chaque mise en page qui ressemble à un type de carte intégré dans Scrollview. Quand je défile, comment déplacer la carte comme le type de ressort et ensuite revenir à la position d'origine.Comment tirer des dispositions similaires à un type élastique lors du défilement Android?

C'est comme si les cartes rebondissaient. Dans ma mise en page, le haut de ce qui est ScrollView, ci-dessous que 5 à 6 mises en page sont intégrées.

Lorsque je fais défiler comment déplacer ces mises en page ajoutées un peu plus haut et arriver à sa position? Vous pouvez voir un exemple ici. Il suffit de regarder le défilement seul où cartes se déplacer de sa position. Il suffit de voir le screenshot notez le défilement où les cartes sont déplacées comme le type de ressort lorsque vous faites défiler vers le haut et vers le bas, c'est-à-dire que l'espacement entre les cartes est réduit lors du défilement. Comment y parvenir?

Actuellement CustomScrollView appliqué, il a overscroll mais je ne pourrais pas réaliser des cartes mobiles de type de ressort.

Voici le code que j'ai appliqué.

<android.support.design.widget.CoordinatorLayout  xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:id="@+id/coordinatorLayout" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
tools:context=".LaunchActivity"> 
    <RelativeLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <com.mobile.ui.MyImageView 
     android:id="@+id/backgroundImage_timeline" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="@drawable/bg_dot_line" 
     android:scaleType="centerCrop" /> 


    <com.mobile.ui.view.ObservableScrollView 
     android:id="@+id/scrollView" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     tools:context=".LaunchActivity"> 

     <RelativeLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content"> 

      <LinearLayout 
       android:id="@+id/commonModules" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:layout_below="@id/anotherModule" 
       android:orientation="vertical"> 

       <com.mobile.ui.FirstModule //this is one layout 
        android:id="@+id/myFirstModule" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:visibility="visible" /> 
       <---second layout-----> and so on.. 
     </RelativeLayout> 
    </com.mobile.ui.view.ObservableScrollView> 

    </RelativeLayout> 

public class ObservableScrollView extends ScrollView { 
private View inner; 

private float y; 

private Rect normal = new Rect(); 

private boolean isCount = false; 

public interface OnOverScrolledListener { 
    void onOverScrolled(android.widget.ScrollView scrollView, 
         int deltaX, int deltaY, boolean clampedX, boolean clampedY); 
} 

private OnOverScrolledListener mOnOverScrolledListener; 

private int mOverScrollByDeltaX; 
private int mOverScrollByDeltaY; 

@Override protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { 
    this.mOverScrollByDeltaX = deltaX; 
    this.mOverScrollByDeltaY = deltaY; 
    final boolean result = super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent); 
    return result; 
}; 
@Override 
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { 
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY); 
    if (mOnOverScrolledListener != null && (clampedX || clampedY)) { 
     mOnOverScrolledListener.onOverScrolled(this, mOverScrollByDeltaX, mOverScrollByDeltaY, clampedX, clampedY); 
    } 
} 

public OnOverScrolledListener getOnOverScrolledListener() { 
    return mOnOverScrolledListener; 
} 

public void setOnOverScrolledListener(OnOverScrolledListener onOverScrolledListener) { 
    this.mOnOverScrolledListener = onOverScrolledListener; 
} 

public ObservableScrollView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 

@SuppressLint("MissingSuperCall") 
@Override 
protected void onFinishInflate() { 
    if (getChildCount() > 0) { 
     inner = getChildAt(0); 
    } 
} 

@Override 
public boolean onTouchEvent(MotionEvent ev) { 
    if (inner != null) { 
     commOnTouchEvent(ev); 
    } 

    return super.onTouchEvent(ev); 
} 

public void commOnTouchEvent(MotionEvent ev) { 
    int action = ev.getAction(); 
    switch (action) { 
     case MotionEvent.ACTION_DOWN: 
      break; 
     case MotionEvent.ACTION_UP: 
      if (isNeedAnimation()) { 
       animation(); 
       isCount = false; 
      } 
      break; 

     case MotionEvent.ACTION_MOVE: 
      final float preY = y; 
      float nowY = ev.getY(); 
      int deltaY = (int) (preY - nowY); 
      if (!isCount) { 
       deltaY = 0; 
      } 

      y = nowY; 
      if (isNeedMove()) { 
       if (normal.isEmpty()) { 

        normal.set(inner.getLeft(), inner.getTop(), 
          inner.getRight(), inner.getBottom()); 
       } 
       inner.layout(inner.getLeft(), inner.getTop() - deltaY/2, 
         inner.getRight(), inner.getBottom() - deltaY/2); 
      } 
      isCount = true; 
      break; 

     default: 
      break; 
    } 
} 

public void animation() { 
    TranslateAnimation ta = new TranslateAnimation(0, 0, inner.getTop(), 
      normal.top); 
    ta.setDuration(200); 
    inner.startAnimation(ta); 
    inner.layout(normal.left, normal.top, normal.right, normal.bottom); 

    normal.setEmpty(); 

} 

public boolean isNeedAnimation() { 
    return !normal.isEmpty(); 
} 

public boolean isNeedMove() { 
    int offset = inner.getMeasuredHeight() - getHeight(); 
    int scrollY = getScrollY(); 
    if (scrollY == 0 || scrollY == offset) { 
     return true; 
    } 
    return false; 
} 

}

Alors alternative, que j'ai essayé est,

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { 
     scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() { 
      @Override 
      public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { 
       View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1); 
       int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY())); 
       if(view.getTop()==scrollY){ 
        // reaches the top end 
        Log.e("scrolled top","scrolling top"); 
       } 


       // if diff is zero, then the bottom has been reached 
       if (diff == 0) { 
        // do stuff L 
        Log.e("bottom reached","bottom reached"); 
       } 
       else { 
        TranslateAnimation animation = new TranslateAnimation(0f, 0f, 0f, -100f); // might need to review the docs 
        animation.setDuration(500); // set how long you want the animation 
        animation.setFillAfter(true); 
        myFirstModule.startAnimation(animation); 
        mySecondModule.startAnimation(animation); 
     //till 10.. 
       } 

      } 
     }); 
    } 

Mais cela ne s'appliqué pendant le défilement. Il y a un peu de retard dans l'animation après le défilement et la vue monte et non pas parfaite.

Répondre

3

Quoi qu'il en soit trouvé une solution :-) J'espère que cela peut être utile pour quelqu'un.

public class ObservableScrollView extends ScrollView { 
    private ScrollCallbacks mCallbacks; 

    private static final int MAX_Y_OVERSCROLL_DISTANCE = 150; 

    private Context mContext; 
    private int mMaxYOverscrollDistance; 

    public ObservableScrollView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.mContext = context; 
     initBounceScrollView(); 
    } 

    @Override 
    protected void onScrollChanged(int l, int t, int oldl, int oldt) { 
     super.onScrollChanged(l, t, oldl, oldt); 
     if (mCallbacks != null) { 
      mCallbacks.onScrollChanged(l, t, oldl, oldt); 
     } 
    } 

    @Override 
    public int computeVerticalScrollRange() { 
     return super.computeVerticalScrollRange(); 
    } 

    public void setCallbacks(ScrollCallbacks listener) { 
     mCallbacks = listener; 
    } 

    private void initBounceScrollView() { 
     // get the density of the screen and do some maths with it on the max 
     // overscroll distance 
     // variable so that you get similar behaviors no matter what the screen 
     // size 

     final DisplayMetrics metrics = mContext.getResources() 
       .getDisplayMetrics(); 
     final float density = metrics.density; 

     mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE); 

    } 

    @Override 
    public void draw(Canvas canvas) { 
     super.draw(canvas); 
    } 

    public interface ScrollCallbacks { 
     void onScrollChanged(int l, int t, int oldl, int oldt); 
    } 

    @SuppressLint("NewApi") 
    @Override 
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, 
            int scrollY, int scrollRangeX, int scrollRangeY, 
            int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { 
     // This is where the magic happens, we have replaced the incoming 
     // maxOverScrollY with our own custom variable mMaxYOverscrollDistance; 
     return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, 
       scrollRangeX, scrollRangeY, maxOverScrollX, 
       mMaxYOverscrollDistance, isTouchEvent); 
    } 
} 

MainActivity:

 scrollView.setCallbacks(new ObservableScrollView.ScrollCallbacks() { 
       @Override 
       public void onScrollChanged(int l, int t, int oldl, int oldt) { 
       Rect scrollBounds = new Rect(); 
        scrollView.getHitRect(scrollBounds); 

    if (myFirstModule.getLocalVisibleRect(scrollBounds)){ 
        if(!myFirstModule.isAnim) { 
         if (myFirstModule.getY() < scrollBounds.top) { 
          myFirstModule.setAnimationView(2); 
         } else { 
          myFirstModule.setAnimationView(1); 
         } 
        } 
        }else{ 
         myFirstModule.isAnim = false; //myFirstModule is layout. In my case, I used layout in separate class. 
        } 

En FirstModule:

// in firstModule i integrated layout which i skipped.. I am focusing only on main thing.. 

    public boolean isAnim = false; 
    private Animation animSlideUp = null; 
    private Animation animSlideDown = null; 
    private void loadAnimation(){ 
     animSlideUp = AnimationUtils.loadAnimation(getContext(), R.anim.bottom_to_top); 
     animSlideDown = AnimationUtils.loadAnimation(getContext(), R.anim.top_to_bottom); 
    } 
    //this i will use in mainactivity. 
    public void setAnimationView(int animType){ 
     if(isVisible()) { 
      isAnim = true; 
      if (animType == 1) { 
       startAnimation(animSlideUp); 
      } else { 
       startAnimation(animSlideDown); 
      } 
     } 
    } 

bottom_to_top:

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shareInterpolator="@android:anim/decelerate_interpolator"> 
    <translate 
     android:fromXDelta="0%" android:toXDelta="0%" 
     android:fromYDelta="300" android:toYDelta="0" 
     android:duration="400" /> 
</set> 

haut en bas:

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shareInterpolator="@android:anim/decelerate_interpolator"> 
    <translate 
     android:fromXDelta="0%" android:toXDelta="0%" 
     android:fromYDelta="-300" android:toYDelta="0" 
     android:duration="400" /> 
</set> 

Voilà. :-) Peut atteindre sans n'importe quelle bibliothèque .. J'espère que cela peut aider quelqu'un.