[Android] 监听ScrollView惯性滑动事件
ScrollView本身并没有对外提供监听方法,好在内部有一个方法可以监听滑动事件。所以如果我们想要监听ScrollView的滑动事件,只需要做以下几点即可。
自定义一个ScrollView继承系统的ScrollView
重写 onScrollChanged 方法
自定义接口监听onScrollChanged,并将其暴露出去
代码如下
public class ListeningScrollView extends ScrollView {
private ScrollListener scrollListener;
public ListeningScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if(scrollListener != null){
scrollListener.onScrollChanged(l,t,oldl,oldt,computeVerticalScrollRange());
}
}
public void setScrollViewListener(ScrollListener scrollListener) {
this.scrollListener = scrollListener;
}
/**
* 滑动监听器
*/
public interface ScrollListener {
void onScrollChanged(int x, int y, int oldx, int oldy,int computeVerticalScrollRange);
}
}
接着问题来了,实验证明刚刚那个方法无法监听到惯性滑动(即只能监听到手指按下时ScrollView的滑动情况),所以我们需要做一下操作,监听手指松开后的惯性滑动事件。
- 重写 onTouchEvent 方法。
- 当 onTouchEvent 方法捕获到手指松开时,隔一段时间getScrollY(),如果数据和上次不一致就说明正在惯性滑动中。
可以监听惯性滚动事件的代码如下
public class ListeningScrollView extends ScrollView {
/**
* 上次的Y坐标
*/
private int lastY = 0;
private ScrollYListener scrollYListener;
private ScrollListener scrollListener;
private static final int SCROLL_TIME = 20;
private static final int SCROLL_WHAT = 111;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SCROLL_WHAT:
int scrollY = getScrollY();
DebugUtils.printLogE("收到滑动事件" + scrollY);
if (lastY != scrollY) {
lastY = scrollY;
scrollYListener.onScrollChanged(scrollY);
handler.sendEmptyMessageDelayed(SCROLL_WHAT, SCROLL_TIME);
}
break;
}
}
};
public ListeningScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollYViewListener(ScrollYListener scrollYListener) {
this.scrollYListener = scrollYListener;
}
public void setScrollViewListener(ScrollListener scrollListener) {
this.scrollListener = scrollListener;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (scrollYListener != null) {
scrollYListener.onScrollChanged(t);
}
if(scrollListener != null){
scrollListener.onScrollChanged(l,t,oldl,oldt,computeVerticalScrollRange());
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
if (scrollYListener != null) {
handler.sendEmptyMessage(SCROLL_WHAT);
DebugUtils.printLogE("发送滑动事件");
}
break;
}
return super.onTouchEvent(ev);
}
/**
* 带惯性的滑动监听器
*/
public interface ScrollYListener {
void onScrollChanged(int y);
}
/**
* 滑动监听器
*/
public interface ScrollListener {
void onScrollChanged(int x, int y, int oldx, int oldy,int computeVerticalScrollRange);
}
}
ITDogFire –弓长剑鸣