android群英传笔记——ListView常用优化技巧(ListView的滑动监听)

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日志并打印出来。需要源码的读者可以点击这里进入上一篇获取下方的源码,其源码已经涵盖了本篇的事件监听。

感谢阅读,学习重在坚持,贵在坚持,那么下次再见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值