2

나는 Scrollview에 내장 된 카드 유형으로 보이는 모든 레이아웃을 가지고 있습니다. 스크롤 할 때 봄철처럼 카드를 옮기고 원래 위치로 내려 오는 법.안드로이드를 스크롤 할 때 탄성 유형과 비슷한 레이아웃을 가져 오는 방법은 무엇입니까?

카드가 튀는 것처럼 보입니다. 내 레이아웃에서, 그 상단은 ScrollView이며, 그 아래에 5 ~ 6 개의 레이아웃이 통합되어 있습니다.

내가 추가 한 레이아웃을 조금 위쪽으로 이동하고 그 위치로 이동하는 방법을 스크롤 할 때? 여기에서 예제를 볼 수 있습니다. 카드가 위치에서 벗어난 곳에서 스크롤 만하면됩니다. screenshot이 스크롤 할 때 스크롤 할 때 스프링 종류와 같이 카드가 상하로 이동할 때 카드 사이의 간격이 줄어들면 스크롤하는 것을 확인하십시오. 그것을 성취하는 방법?

현재 적용되는 CustomScrollView에는 과도기가 있지만 스프링 유형의 이동식 카드를 얻을 수 없습니다.

다음은 내가 적용한 코드입니다.

<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; 
} 

}

그래서 대안, I는 시도

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.. 
       } 

      } 
     }); 
    } 

을하지만이 스크롤 동안 적용 받고 있지 않습니다. 스크롤링과 뷰가 올라간 후에 애니메이션에 약간의 지연이 있습니다. 완벽한 애니메이션이 아닙니다.

답변

3

어쨌든 해결책을 찾았습니다 :-) 누군가에게 도움이되기를 바랍니다.

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 : FirstModule에서

 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. 
        } 

:

// 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> 
아래로 0

최고 : 그것 뿐이다

<?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> 

. :-) 어떤 라이브러리없이 성취 할 수 있습니다. 누군가에게 도움이되기를 바랍니다.

관련 문제