更全面地判断ListView滑动方向

博客内容介绍了如何更准确地判断ListView在Android中的滑动方向,指出仅依赖firstVisibleItem判断的缺陷,并分享了一个开源库com.melnykov:floatingactionbutton:1.3.0中的解决方案,强调学习他人代码的重要性。

一般判断ListView方向的方法大致是:ListView设置滑动监听器:

listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount{
  //根据firstVisibleItem的在滑动前后的不同值,判断滑动方向。
    }
});

但这样有一个问题,如果ListView只滑动一小段距离(不超过一个item的高度),firstVisibleItem是保持不变的啊!这样就判断不了是上滑还是下滑!所以这样做是有缺陷的!
但今天在使用一个控件时。偶然看了其源代码,发现了其中有对ListView方向更全面的判断方法,其实也很简单,代码如下:

import android.support.annotation.NonNull;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;

abstract class AbsListViewScrollDetector implements OnScrollListener {
 private int mLastScrollY; //第一个可视的item的顶部坐标
 private int mPreviousFirstVisibleItem; //上一次滑动的第一个可视item的索引值
 private AbsListView mListView;//列表控件,如ListView
 /**
 *滑动距离响应的临界值,这个值可根据需要自己指定
 *只有只有滑动距离大于mScrollThreshold,才会响应滑动动作
 */
 private int mScrollThreshold;
   AbsListViewScrollDetector() {}
 //当认为ListView向上滑动时会被调用,由子类去定义的。
 abstract void onScrollUp();
 //当认为ListView下滑动时会被调用,由子类去定义的。
 abstract void onScrollDown();

 public void onScrollStateChanged(AbsListView view, int scrollState) { }

//核心方法,该方法封装了滑动方向判断的逻辑,但ListView产生滑动之后,该方法会被调用。
//1.首先,判断滑动后第一个可视的item和滑动前是否同一个,如果是同一个,进入第2步,否则进入第3步
//2.则这次滑动距离小于一个Item的高度,比较第一个可视的item的顶部坐标在滑动前后的差值,就知道了滑动的距离
//3.这个好办,直接比较滑动前后firstVisibleItem的值就可以判断滑动方向了。
 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){
  if(totalItemCount != 0) {  
      // 滑动距离:不超过一个item的高度
     if(this.isSameRow(firstVisibleItem)) { 
       int newScrollY = this.getTopItemScrollY(); 
    //判断滑动距离是否大于 mScrollThreshold
       boolean isSignificantDelta = Math.abs(this.mLastScrollY - newScrollY) > this.mScrollThreshold;
             if(isSignificantDelta) { 
                 //对于第一个可视的item,根据其前后两次的顶部坐标判断滑动方向
                 if(this.mLastScrollY > newScrollY) {
                     this.onScrollUp();
                 } else {
                     this.onScrollDown();
                 }
             }
             this.mLastScrollY = newScrollY;
         } else {//根据第一个可视Item的索引值不同,判断滑动方向
             if(firstVisibleItem > this.mPreviousFirstVisibleItem) {
                 this.onScrollUp();
             } else {
                 this.onScrollDown();
             }
             this.mLastScrollY = this.getTopItemScrollY();
             this.mPreviousFirstVisibleItem = firstVisibleItem;
         }
     }
 }

 public void setScrollThreshold(int scrollThreshold) {
     this.mScrollThreshold = scrollThreshold;
 }

 public void setListView(@NonNull AbsListView listView) {
     this.mListView = listView;
 }

 private boolean isSameRow(int firstVisibleItem) {
     return firstVisibleItem == this.mPreviousFirstVisibleItem;
 }

 private int getTopItemScrollY() {
     if(this.mListView != null && this.mListView.getChildAt(0) != null) {
         View topChild = this.mListView.getChildAt(0);
         return topChild.getTop();
      } else {
         return 0;
     }
  }
 }
----------------------------我是分给线-----------------------------------

多看别人造的轮子还是很用的!
对了,这个我看的是这个开源库的:com.melnykov:floatingactionbutton:1.3.0。
Android studio 上应该能找到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值