检测ScrollView开始停止滑动的方案

来源:互联网 发布:京东跟淘宝有什么区别 编辑:程序博客网 时间:2024/06/10 03:00

检测ScrollView开始停止滑动的方案

旧方案

如何检测scrollview的滑动开始和滑动停止,滑动开始可以用
onScrollChange来判断,那么停止呢。
一开始的时候我是判断200ms内,scrollY是否改变,如果未改变就判断为停止了,核心代码如下。工程名为DetectScrollStop。但是这样不优雅,有没有更好的方法呢?

        detector = new ScrollViewStopDetector(scrollView);        scrollView.addOnScrollChangeListener(new FixedNestedScrollView.OnScrollChangeListener() {            @Override            public void onScrollChange(FixedNestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {                detector.start();            }        });       detector.setListener(new ScrollViewStopDetector.OnScrollStateListener() {            @Override            public void onStop() {                anim.animShow();            }            @Override            public void onStart() {                anim.animHide();            }        });
public class ScrollViewStopDetector {    private static final int SCROLLING = 0;    private static final int IDLE = 1;    private int state=IDLE;    public interface OnScrollStateListener {        void onStop();        void onStart();    }    public ScrollViewStopDetector(FixedNestedScrollView scrollView) {        this.scrollView = scrollView;    }    public OnScrollStateListener getListener() {        return listener;    }    public void setListener(OnScrollStateListener listener) {        this.listener = listener;    }    private OnScrollStateListener listener;    private Handler handler = new Handler();    private FixedNestedScrollView scrollView;    private int lastScrollY;    public void start() {        LogUtil.fish("start");        setState(SCROLLING);        handler.removeCallbacksAndMessages(null);        lastScrollY = scrollView.getScrollY();        handler.postDelayed(runnable, 200);    }    private Runnable runnable = new Runnable() {        @Override        public void run() {            int nowScrollY = scrollView.getScrollY();            if (!scrollView.isBeingDragged()&&nowScrollY == lastScrollY) {                //表示停止了                LogUtil.fish("setState idle");                setState(IDLE);            } else {                //再等200ms                LogUtil.fish("again");                handler.postDelayed(runnable, 200);            }            lastScrollY = nowScrollY;        }    };    private void setState(int newState) {        if (newState != state) {            state = newState;            if (state == SCROLLING) {                listener.onStart();            } else {                listener.onStop();            }        }    }}

新方案

想了下,scrollview的滑动停止有以下3种情况
1、滑动,然后停止
2、fling 然后减速停止
3、fling,触底停止
4、fling,然后点击,然后停止

那么我在scrollview里检测,然后给他设置好相应的scrollstate,就可以了。参考listview,我把state分成3类,SCROLL_STATE_IDLE、SCROLL_STATE_TOUCH_SCROLL、SCROLL_STATE_FLING。第一种情况和第四种情况都好办,在onTouchEvent的事件里处理就好了。

2和3比较麻烦,首先看2,因为不知道什么时候2停止下来,只能通过监测computesScroll来实现。一开始的时候,我是认为,在下面的case1,和case2里来检测就行了。但是drag的时候会进入到case2,不行,所以我们只关注case 1,没错case1 可以检测到情况2(
if (oldX != x || oldY != y)不成立的时候,就认为fling停止了。),但是无法检测到情况3,如何检测情况3呢?对于3呢,触底的时候会调用springBack,所以我直接粗暴的在springBack的时候认为fling停止了。工程名为DetectScrollStop2

    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            int oldX = getScrollX();            int oldY = getScrollY();            int x = mScroller.getCurrX();            int y = mScroller.getCurrY();            if (oldX != x || oldY != y) {                final int range = getScrollRange();                final int overscrollMode = ViewCompat.getOverScrollMode(this);                final boolean canOverscroll = overscrollMode == ViewCompat.OVER_SCROLL_ALWAYS ||                        (overscrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);                overScrollByCompat(x - oldX, y - oldY, oldX, oldY, 0, range,                        0, 0, false);                if (canOverscroll) {                    ensureGlows();                    if (y <= 0 && oldY > 0) {                        mEdgeGlowTop.onAbsorb((int) mScroller.getCurrVelocity());                    } else if (y >= range && oldY < range) {                        mEdgeGlowBottom.onAbsorb((int) mScroller.getCurrVelocity());                    }                }            }else{                //case1                 reportScrollStateChange(OnScrollStateChangeListener.SCROLL_STATE_IDLE);            }        }else{                //case 2reportScrollStateChange(OnScrollStateChangeListener.SCROLL_STATE_IDLE);        }    }
阅读全文
1 0
原创粉丝点击