上一篇文章我讲到用事件分发的原理结合SwipeRefreshLayout写一个RecyclerView的上下拉,里面有一个判断RecyclerView是否到达底部的方法isBottom。我的同事用了这个上下拉之后发现有些小bug,没考虑周全,譬如各个子项高度不统一的时候,然后我找到原因是因为这个判断上下拉的问题。所以,我就去网上查到几种判断RecyclerView到达底部的方法,发现各有千秋。以下的分析都以上一篇文章的SwipeRecyclerView为例。

1.lastVisibleItemPosition == totalItemCount - 1判断;
2.computeVerticalScrollRange()等三个方法判断;
3.canScrollVertically(1)判断;
4.利用RecyclerView的LinearLayoutManager几个方法判断。

其实,第2和第3种是属于同一种方法,在下面的分析会讲到。

一、首先,我们来介绍和分析一下第一种方法,也是网上最多人用的方法:

public static boolean isVisBottom(RecyclerView recyclerView){  LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();  //屏幕中最后一个可见子项的positionint lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();  //当前屏幕所看到的子项个数int visibleItemCount = layoutManager.getChildCount();  //当前RecyclerView的所有子项个数int totalItemCount = layoutManager.getItemCount();  //RecyclerView的滑动状态int state = recyclerView.getScrollState();  if(visibleItemCount > 0 && lastVisibleItemPosition == totalItemCount - 1 && state == recyclerView.SCROLL_STATE_IDLE){   return true; }else {   return false;  }
}

很明显,当屏幕中最后一个子项lastVisibleItemPosition等于所有子项个数totalItemCount - 1,那么RecyclerView就到达了底部。但是,我在这种方法中发现了极为极端的情况,就是当totalItemCount等于1,而这个子项的高度比屏幕还要高。

item_recycleview.png

看看效果图:

效果图.png

我们可以发现这个子项没完全显示出来就已经被判断为拉到底部。当然,这种方法一般情况下都能满足开发者的需求,只是遇到了强迫症的我~

二、下面我们介绍第二种方法:

public static boolean isSlideToBottom(RecyclerView recyclerView) {    if (recyclerView == null) return false; if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset() >= recyclerView.computeVerticalScrollRange())   return true;  return false;
}

这种方法原理其实很简单,而且也是View自带的方法。

原理图.png

这样就很清晰明了,computeVerticalScrollExtent()是当前屏幕显示的区域高度,computeVerticalScrollOffset() 是当前屏幕之前滑过的距离,而computeVerticalScrollRange()是整个View控件的高度。
这种方法经过测试,暂时还没发现有bug,而且它用的是View自带的方法,所以个人觉得比较靠谱。

三、下面讲讲第三种方法:

RecyclerView.canScrollVertically(1)的值表示是否能向上滚动,false表示已经滚动到底部
RecyclerView.canScrollVertically(-1)的值表示是否能向下滚动,false表示已经滚动到顶部

这种方法更简单,就通过简单的调用方法,就可以得到你想要的结果。我一讲过这种方法与第二种方法其实是同一种方法,那下面来分析一下,看看canScrollVertically的源码:

canScrollVertically的源码

是不是一目鸟然了,canScrollVertically方法的实现实际上运用到的是方法二的三个函数,只是这个方法Android已经帮我们封装好了,原理一模一样的。
本人现在也是运用了这种方法做判断的懒人工具类都省了~

四、最后一种方法其实是比较呆板的,就是利用LinearLayoutManager的几个方法,1.算出已经滑过的子项的距离,2.算出屏幕的高度,3.算出RecyclerView的总高度。然后用他们做比较,原理类似于方法二。

public static int getItemHeight(RecyclerView recyclerView) {  int itemHeight = 0;  View child = null;  LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();  int firstPos = layoutManager.findFirstCompletelyVisibleItemPosition(); int lastPos = layoutManager.findLastCompletelyVisibleItemPosition();  child = layoutManager.findViewByPosition(lastPos);  if (child != null) {   RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();   itemHeight = child.getHeight() + params.topMargin + params.bottomMargin;  }   return itemHeight;}

算出一个子项的高度

public static int getLinearScrollY(RecyclerView recyclerView) {  int scrollY = 0;  LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();  int headerCildHeight = getHeaderHeight(recyclerView);  int firstPos = layoutManager.findFirstVisibleItemPosition();  View child = layoutManager.findViewByPosition(firstPos);  int itemHeight = getItemHeight(recyclerView);  if (child != null) {   int firstItemBottom = layoutManager.getDecoratedBottom(child);   scrollY = headerCildHeight + itemHeight * firstPos - firstItemBottom;    if(scrollY < 0){    scrollY = 0;    }  }  return scrollY;
}

算出滑过的子项的总距离

public static int getLinearTotalHeight(RecyclerView recyclerView) {    int totalHeight = 0;  LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();  View child = layoutManager.findViewByPosition(layoutManager.findFirstVisibleItemPosition());  int headerCildHeight = getHeaderHeight(recyclerView);  if (child != null) {   int itemHeight = getItemHeight(recyclerView);    int childCount = layoutManager.getItemCount();    totalHeight = headerCildHeight + (childCount - 1) * itemHeight;  }  return totalHeight;
}

算出所有子项的总高度

public static boolean isLinearBottom(RecyclerView recyclerView) {
boolean isBottom = true;  int scrollY = getLinearScrollY(recyclerView);  int totalHeight = getLinearTotalHeight(recyclerView); int height = recyclerView.getHeight();//    Log.e("height","scrollY  " + scrollY + "  totalHeight  " +  totalHeight + "  recyclerHeight  " + height);  if (scrollY + height < totalHeight) {    isBottom = false;  }  return isBottom;
}

高度作比较
虽然这种方法看上去比较呆板的同时考虑不很周全,但这种方法可以对RecylerView的LinearLayoutManager有深一步的理解,这也是我的师兄给我提供的一个借鉴的类,我非常感谢他!有兴趣的同学可以去下载源码的做进一步的研究,发现有更好玩的方法可以一起研究!
源码下载链接

作者:19snow93
链接:https://www.jianshu.com/p/c138055af5d2
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

总结和分析几种判断RecyclerView到达底部的方法相关推荐

  1. Excel:5种判断奇数和偶数的方法

    整数中,能被2整除的数是偶数(英文:EVEN,数学术语),不能被2整除的数是奇数(英文:ODD,数学术语),偶数可用2k表示,奇数可用2k+1表示,这里k是整数.0是一个特殊的偶数.那么,该如何使用E ...

  2. Java判断三个球的大中小_玩进球数有门道 三种判断大小球的典型方法

    竞彩进球数玩法是竞彩一个主要玩法,比半全场更加受欢迎.因为很多彩民习惯了大小球玩法,因此,作为大球的变种,进球数受到这部分彩民的热捧.不过,市面上介绍亚盘的方法较多,介绍判断大小球的方法却很少.为此, ...

  3. 在vue中如何判断滚动条到达底部

    mounted(){//在生命周期函数mounted中console.log(this.$refs.veriface,'智能切分滚动组件实例')//具有滚动条的dom元素,this.$refs.ver ...

  4. 如何判断无法到达目标的拼图_拼图项目的动机和目标

    如何判断无法到达目标的拼图 几周前,我写了一篇关于Jigsaw项目可能如何破坏现有代码的文章 . 那么我们得到什么回报呢? 让我们看一下项目解决的痛点及其在Java 9中解决问题的目标. 系列 这篇文 ...

  5. 逐步认识C#四种判断相等的方法

    C#有四种判断相等的方法?不少人看到这个标题,会对此感到怀疑.事实上确是如此,.Net提供了ReferenceEquals.静态Equals,具体类型的Equals以及==操作符这四个判等函数.但是这 ...

  6. 7-32 哥尼斯堡的“七桥问题” (25 分)(思路+详解+题目分析)两种做法任选其一

    一:题目: 哥尼斯堡是位于普累格河上的一座城市,它包含两个岛屿及连接它们的七座桥,如下图所示. 可否走过这样的七座桥,而且每桥只走过一次?瑞士数学家欧拉(Leonhard Euler,1707-178 ...

  7. sql查询当天交易总额最大的用户信息_如何分析交易记录? 因为后面要分析“每种类型用户的总交易金额”,所以保留左表(用户交易记录表)中的全部用户数据。 【题目】 某商场为了分析用... - 雪球...

    来源:雪球App,作者: 猴子数据分析,(https://xueqiu.com/1350621016/159703178) 因为后面要分析"每种类型用户的总交易金额",所以保留左表 ...

  8. 关于定义域有界性的三种判断

    关于定义域有界性的三种判断 @(微积分) 给定一个函数,讨论其在定义域上是否有界,有三种方法.不敢说常见,提出来思考. 理论法:若f(x)在定义域[a,b]上连续,或者放宽到常义可积(有限个第一类间断 ...

  9. (笔记)两种判断奇数偶数的方法

    (笔记)两种判断奇数偶数的方法 学习的需要,查找了如何判断奇偶数的方法,自己做了以下笔记. 方法来自网络,已标明出处. 方法一 .求余% 具体实现: 1.if( x % 2 )     // 奇数   ...

最新文章

  1. 2017.12.20-21
  2. LeetCode 840. 矩阵中的幻方(数学)
  3. windows mobile 服务自动停止_打印服务print Splooer自动停止怎么办?
  4. 你的个人信息真的被偷走了?——那些过分“精准”的广告推荐的背后
  5. 剑指 Offer II 036. 后缀表达式
  6. mysql hy000 2013_MySQLERROR2013(HY000)错误解决方法
  7. Eclipse快捷键_10个最高效的快捷键
  8. 进程/线程间通信和同步
  9. 使用Jacob自动替换书签内容
  10. Xshell 7官网免费版下载与安装(详细教程)
  11. 邮件营销如何“爆增”潜在客户?
  12. 关系代数 元组关系演算
  13. android textview html font标签不好用
  14. 随机漫步python程序
  15. bigworld游戏服务器架构参考
  16. 33个高能CSS选择器让我受益匪浅
  17. python图片转文字easyocr_OCR识别软件将图片转文字的具体方法
  18. LaTeX 插入PDF图片,该用哪个命令?
  19. CCF-CSP 202112-3登机牌条码 解题思路+满分题解+详细注释
  20. 莫烦python系列教程_莫烦python教程学习笔记——总结篇

热门文章

  1. python程序调试logging_python-logging模块的简单使用
  2. 类成员_月隐学python第17课
  3. python多线程共享全局变量_Python多线程-共享全局变量
  4. c语言电子计算器课程设计报告,计算机程序设计课程设计报告.doc
  5. 下次激活策略10_服装店营销策划方案,简单策略让服装超市提升10倍业绩
  6. 20220207-CTF-MISC-第11题--- base64隐写--附带脚本
  7. html中地图的绘制toolbars,三维GIS实验一:Surfer8地理信息制图.doc
  8. 接口测试学习——jmeter分布式压测
  9. python多线程理解
  10. 不用asp.net MVC,用WebForm照样能够实现MVC