ListView的滑动事件监听是ListView的最重要技巧,很多重写的ListView基本上都是在滑动事件的处理上下功夫,通过滑动事件进行不同的逻辑处理。这里主要介绍两种监听事件:onTouchListener和onScrollListener。为了更加精确地监听滑动事件,开发者通常还需要使用GestureDetector手势识别, VelocityTracker滑动速度检测等辅助类来完成更好的监听。
ListView 的滑动监听
1、onTouchListener
对于这个触摸事件监听之前就已经在事件的拦截机制里解释过,没了解过的读者可以点击进入事件的拦截机制来了解触摸事件。
以下是onTouchListener监听事件的实现代码:
mListView.setOnTouchListener(new View.onTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
// 触碰到时的操作
Log.i(TAG, "onTouch: ACTION_DOWN!");
break;
case MotionEvent.ACTION_MOVE:
// 移动时的操作
Log.i(TAG, "onTouch: ACTION_MOVE!");
break;
case MotionEvent.ACTION_UP:
// 离开时操作
Log.i(TAG, "onTouch: ACTION_UP!");
break;
}
return false;
}
})
2、onScrollListener
这是AbsListView中的监听事件,它封装和许多和ListView相关的信息,使用起来更加灵活。首先来看一下OnScrollListener的一般使用方法,代码如下所示:
mListView.setOnScrollListener(new OnScrollListener(){
/**
* 监听滑动状态
* @param view 监听的控件
* @param scrollState 监听控件的状态
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState){
case OnListScrollListener.SCROLL_STATE_IDLE:
// 滑动停止时
Log.d(TAG, "onScrollStateChanged: scrollStop!");
break;
case OnListScrollListener.SCROLL_STATE_TOUCH_SCROLL:
// 正在滑动
Log.d(TAG, "onScrollStateChanged: scrolling!");
break;
case OnListScrollListener.SCROLL_STATE_FLING:
// 手指抛动时,即手指用力滑动在离开后ListView由于惯性继续滑动
Log.d(TAG, "onScrollStateChanged: scrollFling!");
break;
}
}
/**
* 监听listView的滚动状态
* @param view 当前view
* @param firstVisibleItem 第一个显示的子项id
* @param visibleItemCount 可见的子项总数,包括显示部分的子项
* @param totalItemCount 子项的总数
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// 滚动时一直调用
Log.d(TAG, "onScroll: onScroll!!!");
if(firstVisibleItem+visibleItemCount==totalItemCount && totalItemCount>0){
// 滚动到最后一行
Log.d(TAG, "onScroll: OnLastItem!");
}
}
})
在onScrollListener中有两个方法:onScrollStateChanged和onScroll。
先来看看onScrollStateChanged方法,它通过scrollState来决定其回调的次数,scrollState有以下三种模式:
- OnScrollListener.SCROLL_STATE_IDLE:滚动停止时。
- OnListScrollListener.SCROLL_STATE_TOUCH_SCROLL:正在滚动时。
- OnListScrollListener.SCROLL_STATE_FLING:ListView的快速滑动造成惯性的状态。
当用户没有快速滑动,未造成惯性滑动,则此方法只调用两次,即:SCROLL_STATE_IDLE和SCROLL_STATE_TOUCH_SCROLL状态。否则三次,即三个状态都存在。通常通过设置flag来区分各个状态,共其他方法处理。
再来看看onScroll回调方法,这个回调方法只要ListView滑动则一直回调这个方法,之前笔者试过在此方法内加入一个Toast,后来发现这个Toast一直弹出,也就说明确实在ListView滑动的时候就调用此方法。如果在此方法内做操作,可能会多次重复调用,所以在使用前先想好是不是需要一直调用。当然,方法中的三个int类型参数,则非常精确的显示了当前ListView的滚动状态,这三个参数如下所示:
- firstVisibleItem:当前能看到的第一个子项的ID(ID从0开始)。
- visibleItemCount:当前能看到的子项总数。
totalItemCount:整个ListView的子项总数。
注意:这里能看到的子项包括没有显示完整的子项,即便是只显示一小部分也算一个子项。 通过以上参数可以很方法的做一些判断,举几个简单的例子:
if(firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0){
// 已经滚动到了最后一行
}
再比如,通过如下代码可以判断滚动方向,代码如下所示:
if(firstVisibleItem > lastVisibleItemPosition){
// 上滑
} else if(firstVisibleItem < lastVisibleItemPosition){
// 下滑
}
// 记录本次第一个可见子项的ID
lastVisibleItemPosition = firstVisibleItem;
通过定义一个变量来进行记录上次第一个可见子项的ID并与当前第一个可见子项的ID进行比较,即可知道其滚动方向。
当然,ListView也给我们提供了一些封装的方法获得当前可见的子项位置等信息:
// 获取可见区域内的最后一个子项的ID
mListView.getLastVisiblePosition();
// 获取可见区域内的第一个子项的ID
mListView.getFirstVisiblePosition();
要想了解这个OnScrollListener,最好的方法就是在代码中添加log日志并打印出来。需要源码的读者可以点击这里进入上一篇获取下方的源码,其源码已经涵盖了本篇的事件监听。
感谢阅读,学习重在坚持,贵在坚持,那么下次再见。