【问题标题】:How to pull layouts similar to elastic type when scrolling android?滚动android时如何拉出类似于弹性类型的布局?
【发布时间】:2018-06-23 00:49:23
【问题描述】:

我的每一个布局都看起来像嵌入在 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;
}

}

所以我尝试过的替代方案是,

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

            }
        });
    }

但这在滚动期间没有得到应用。滚动和视图上升后动画有一些延迟,而不是完美的。

【问题讨论】:

    标签: android animation android-animation android-scrollview bounce


    【解决方案1】:

    我找到了解决办法:

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

    主活动:

         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>
    

    从上到下:

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

    就是这样。 :-) 无需任何库即可实现。

    【讨论】:

      猜你喜欢
      • 2018-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-12
      • 1970-01-01
      • 2012-12-25
      • 1970-01-01
      相关资源
      最近更新 更多