您的位置:首页 > 其它

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

2017-08-17 15:05 676 查看

检测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 2
reportScrollStateChange(OnScrollStateChangeListener.SCROLL_STATE_IDLE);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: