RecyclerView 判断滑到底/顶部的方法

判断RecyclerView到达底部的几种方法

项目中的案例

  1. mRvChat.addOnScrollListener(new RecyclerView.OnScrollListener() {
  2. private int minLeftItemCount=10;//剩余多少条时开始加载更多
  3. @Override
  4. public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
  5. if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
  6. LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
  7. int itemCount = layoutManager.getItemCount();
  8. int lastPosition = layoutManager.findLastCompletelyVisibleItemPosition();
  9. XLog.tag("bqt3").i("【总数】" + itemCount + "【位置】" + lastPosition);
  10. if (lastPosition == layoutManager.getItemCount() - 1) {//容错处理,保证滑到最后一条时一定可以加载更多
  11. this.onLoadMore();
  12. } else {
  13. if (itemCount > minLeftItemCount) {
  14. if (lastPosition == itemCount - minLeftItemCount) {
  15. //一定要意识到,onScrolled方法并不是一直被回调的,估计最多一秒钟几十次
  16. //所以当此条件满足时,可能并没有回调onScrolled方法,也就不会调用onLoadMore方法
  17. //所以一定要想办法弥补这隐藏的bug,最简单的方式就是当滑到最后一条时一定可以加载更多
  18. this.onLoadMore();
  19. }
  20. } else {//(第一次进入时)如果总数特别少,直接加载更多
  21. this.onLoadMore();
  22. }
  23. }
  24. }
  25. }
  26. private void onLoadMore() {
  27. if (canLoadMore) {
  28. canLoadMore = false;
  29. ChatReqHelper.requestGroupHis(groupId, ((ChatModel) mGroupChats.get(mGroupChats.size() - 1)).getMsgId());
  30. XLog.tag("bqt3").i("【加载更多数据】");
  31. }
  32. }
  33. });

利用 lastVisibleItemPosition 判断

简单判断

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

当屏幕中最后一个子项 lastVisibleItemPosition 等于所有子项个数 totalItemCount - 1,那么RecyclerView就到达了底部。

但是,如果 totalItemCount 等于1,并且这个item的高度比屏幕还要高时,我们可以发现这个item没完全显示出来就已经被判断为拉到底部。

利用 computeVerticalScrollRange 等判断

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

  1. public static boolean isSlideToBottom(RecyclerView recyclerView) {
  2. return recyclerView != null
  3. && recyclerView.computeVerticalScrollExtent()//当前屏幕显示区域的高度
  4. + recyclerView.computeVerticalScrollOffset()//当前屏幕之前滑过的距离
  5. >= recyclerView.computeVerticalScrollRange();//整个View控件的高度
  6. }

这种方法经过测试,暂时还没发现有bug,而且它用的是View自带的方法,所以个人觉得比较靠谱。

利用 canScrollVertically(direction) 判断

这种方法更简单,就通过简单的调用方法,就可以得到你想要的结果。

这种方法与第二种方法其实是同一种方法,我们看看 canScrollVertically 的源码:

  1. /**
  2. * Check if this view can be scrolled vertically in a certain direction.
  3. *
  4. * @param direction Negative to check scrolling up, positive to check scrolling down.
  5. * @return true if this view can be scrolled in the specified direction, false otherwise.
  6. */
  7. public boolean canScrollVertically(int direction) {
  8. final int offset = computeVerticalScrollOffset();
  9. final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
  10. if (range == 0) return false;
  11. if (direction < 0) {
  12. return offset > 0;
  13. } else {
  14. return offset < range - 1;
  15. }
  16. }

canScrollVertically(1)的值表示是否能向上滚动,true表示能滚动,false表示已经滚动到底部

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

利用 LinearLayoutManager 来判断

这种方法其实是比较呆板的,就是利用LinearLayoutManager的几个方法算出已经滑过的子项的距离、屏幕的高度、RecyclerView的总高度,最后将高度作比较。

算出一个子项的高度

  1. public static int getItemHeight(RecyclerView recyclerView) {
  2. int itemHeight = 0;
  3. View child = null;
  4. LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
  5. int firstPos = layoutManager.findFirstCompletelyVisibleItemPosition();
  6. int lastPos = layoutManager.findLastCompletelyVisibleItemPosition();
  7. child = layoutManager.findViewByPosition(lastPos);
  8. if (child != null) {
  9. RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
  10. itemHeight = child.getHeight() + params.topMargin + params.bottomMargin;
  11. }
  12. return itemHeight;
  13. }

算出滑过的子项的总距离

  1. public static int getLinearTotalHeight(RecyclerView recyclerView) {
  2. int totalHeight = 0;
  3. LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
  4. View child = layoutManager.findViewByPosition(layoutManager.findFirstVisibleItemPosition());
  5. int headerCildHeight = getHeaderHeight(recyclerView);
  6. if (child != null) {
  7. int itemHeight = getItemHeight(recyclerView);
  8. int childCount = layoutManager.getItemCount();
  9. totalHeight = headerCildHeight + (childCount - 1) * itemHeight;
  10. }
  11. return totalHeight;
  12. }

算出所有子项的总高度

  1. public static boolean isLinearBottom(RecyclerView recyclerView) {
  2. boolean isBottom = true;
  3. int scrollY = getLinearScrollY(recyclerView);
  4. int totalHeight = getLinearTotalHeight(recyclerView);
  5. int height = recyclerView.getHeight();
  6. // Log.e("height","scrollY " + scrollY + " totalHeight " + totalHeight + " recyclerHeight " + height);
  7. if (scrollY + height < totalHeight) {
  8. isBottom = false;
  9. }
  10. return isBottom;
  11. }

其他

  1. public static int getHeaderHeight(RecyclerView recyclerView) {
  2. int headerCildHeight = 0;
  3. LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
  4. int firstHeaderPos = layoutManager.findFirstCompletelyVisibleItemPosition();
  5. View headerCild = layoutManager.findViewByPosition(firstHeaderPos);
  6. if (headerCild != null) {
  7. RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) headerCild.getLayoutParams();
  8. headerCildHeight = headerCild.getHeight() + params.topMargin + params.bottomMargin;
  9. }
  10. return headerCildHeight;
  11. }
  12. public static int getLinearScrollY(RecyclerView recyclerView) {
  13. int scrollY = 0;
  14. LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
  15. int headerCildHeight = getHeaderHeight(recyclerView);
  16. int firstPos = layoutManager.findFirstVisibleItemPosition();
  17. View child = layoutManager.findViewByPosition(firstPos);
  18. int itemHeight = getItemHeight(recyclerView);
  19. if (child != null) {
  20. int firstItemBottom = layoutManager.getDecoratedBottom(child);
  21. scrollY = headerCildHeight + itemHeight * firstPos - firstItemBottom;
  22. if (scrollY < 0) {
  23. scrollY = 0;
  24. }
  25. }
  26. return scrollY;
  27. }

虽然这种方法看上去比较呆板的同时考虑不很周全,但这种方法可以对RecylerView的LinearLayoutManager有深一步的理解!

null

时间: 2024-10-12 07:03:10

RecyclerView 判断滑到底/顶部的方法的相关文章

jquery ajax中支持哪些返回类型以及js中判断一个类型常用的方法?

1 jquery ajax中支持哪些返回类型在JQuery中,AJAX有三种实现方式:$.ajax() , $.post , $.get(). 预期服务器返回的数据类型.如果不指定,jQuery 将自动根据 HTTP 包 MIME 信息来智能判断,比如 XML MIME 类型就被识别为 XML.在 1.4 中,JSON 就会生成一个 JavaScript 对象,而 script 则会执行这个脚本.随后服务器端返回的数据会根据这个值解析后,传递给回调 函数.可用值: •"xml": 返回

H5案例分享:移动端touch事件判断滑屏手势的方向

移动端touch事件判断滑屏手势的方向 方法一 当开始一个touchstart事件的时候,获取此刻手指的横坐标startX和纵坐标startY: 当触发touchmove事件时,在获取此时手指的横坐标moveEndX和纵坐标moveEndY;最后,通过这两次获取的坐标差值来判断手指在手机屏幕上的滑动方向. 思路:用touchmove的最后坐标减去touchstart的起始坐标,X的结果如果正数,则说明手指是从左往右划动:X的结果如果负数,则说明手指是从右往左划动:Y的结果如果正数,则说明手指是从

头部显示提示,如tableview滑动提示滑回顶部

头部显示提示,如tableview滑动提示滑回顶部 by 伍雪颖 就是在[[[UIApplication sharedApplication] delegate] window]添加要的内容: #import "TipsBar.h" @implementation TipsBar UILabel *tipsLabel; int width; + (void)showInView:(UIView *)view { width = view.frame.size.width; if (ti

PHP判断移动设备来源的方法

现在移动设备大热的年代,可能我们在做web前端开发的时候经常会需要用到对移动设备的页面匹配.当然我们可以用响应式页面设计来处理前端的匹配问题,但是响应式页面只是不显示某些代码,但是还是会加载到用户的移动设备中.为了更好的照顾到用户手机浏览的体验,减少不必要的加载.我们可以再通过PHP的方式来减少用户的代码加载,提高用户浏览页面时的体验.由于现在移动设备的种类繁多.而且浏览器五花八门,所以仅仅是通过User-Agent来判断已经不能完全解决问题了. <?php function isMobile(

(转)JavaScript中判断对象类型的种种方法

我们知道,JavaScript中检测对象类型的运算符有:typeof.instanceof,还有对象的constructor属性: 1) typeof 运算符 typeof 是一元运算符,返回结果是一个说明运算数类型的字符串.如:"number","string","boolean","object","function","undefined"(可用于判断变量是否存在). 但 type

Shell脚本中判断输入参数个数的方法投稿:junjie 字体:[增加 减小] 类型:转载

Shell脚本中判断输入参数个数的方法 投稿:junjie 字体:[增加 减小] 类型:转载 这篇文章主要介绍了Shell脚本中判断输入参数个数的方法,使用内置变量$#即可实现判断输入了多少个参数,需要的朋友可以参考下 $#代表了命令行的参数数量,可以看以下实例: 复制代码 代码如下: if [ $# != 1 ] ; then echo "USAGE: $0 TABNAME" echo " e.g.: $0 CDR_CALL_20040701" exit 1; f

Javascript判断文件是否存在的方法示例

分享下javascript判断文件是否存在的方法. 1,判断客户端文件时,可以用var fso,s=filespec; // filespec="C:/path/myfile.txt"fso=new ActiveXObject("Scripting.FileSystemObject");if(fso.FileExists(filespec))s+=" exists.";else // www.jbxue.coms+=" doesn't

转:WebDriver(Selenium2) 判断页面是否刷新的方法

Java代码   public static boolean waitPageRefresh(WebElement trigger) { int refreshTime = 0; boolean isRefresh = false; try { for (int i = 1; i < 60; i++) { refreshTime = i; trigger.getTagName(); Thread.sleep(1000); } } catch (StaleElementReferenceExcep

判断中文版、英文版的方法

2013:Autodesk.AutoCAD.DatabaseServices.HostApplicationServices.Current.UserRegistryProductRootKey 2010:Autodesk.AutoCAD.Runtime.SystemObjects.DynamicLinker.ProductKey; 中文版返回值包含:[:804] 英文版返回值包含:[:409] 判断中文版.英文版的方法