监听ScrollView滚动事件
方式一
mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
Log.d("MainActivity", "getViewTreeObserver - onScrollChanged");
}
});
方式二
SdkVersion >= 23时,可直接设置OnScrollChangeListener
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
Log.d("MainActivity", "setOnScrollChangeListener - onScrollChange");
}
});
}
低版本SDK,可以覆写ScrollView中的onScrollChange方法实现监听。
监听ScrollView滚动状态变化(滚动开始、滚动停止)
ListView有个setOnScrollListener的接口,可以监听滚动状态变化,有三种状态:
- 用户触摸状态下的滚动(TOUCH_SCROLL)
- 用户释放手指后继续滚动(FLING)
- 滚动停止(IDLE)
但ScrollView没有提供这种接口。
自己实现监听滚动停止比较简单的一个思路是:触发滚动后,不断读取ScrollView的ScrollY,当两次ScrollY相同时,认为滚动停止了。
判断手指是否按下的实现
区分TOUCH_SCROLL和FLING状态的方法是,通过判断Touch事件,记录当前用户手指是否处于按下状态。
处理ACTION_DOWN事件,应该在ScrollView的onInterceptTouchEvent中实现;
而处理ACTION_UP和ACTION_CANCEL事件,应该在ScrollView的onTouchEvent中实现。
判断滚动是否停止
每次回调onScrollChange时,清除并重启一个延时计时器,计时完成后读取ScrollY,同时启动下一次计时,判断两次ScrollY相同,则置为IDLE状态。
当用户手指处于按下状态时,即使两次检测到ScrollY相同,也不能视为滚动停止。
计时器的间隔要取合适。取太长,会导致检测到滚动停止的延迟比较长;如果取太短,会造成滚动快要停止时,由于滚动很慢,两次间隔时间点可能都没有滚动,造成误判。
完整代码可在GitHub查看:
https://github.com/jzj1993/ObservableScrollView/blob/master/library/src/main/java/com/jzj/view/ObservableScrollView.java
ObservableScrollView
ObservableScrollView是一个可以实现滚动状态监听的开源项目。已经发布到JCenter,可直接通过gradle引用,配置如下。
最新版本请移步项目主页:https://github.com/jzj1993/ObservableScrollView
dependencies {
//...
compile 'com.jzj.view:ObservableScrollView:0.0.2'
}