Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

RecyclerView 判断滑到底部 顶部 预加载 更多 分页 MD


目录

目录
项目中的案例【预加载】
项目中的另一个案例
利用 lastVisibleItemPosition 判断【不靠谱】
利用 computeVerticalScrollRange 等判断【不靠谱】
利用 canScrollVertically(direction) 判断【比较靠谱】
利用 LinearLayoutManager 来判断【垃圾】

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

项目中的案例【预加载】

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

项目中的另一个案例

rv.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {super.onScrolled(recyclerView, dx, dy);StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) rv.getLayoutManager();int[] positions = layoutManager.findLastVisibleItemPositions(null);if (positions != null && positions.length > 0) {for (int position : positions) {if (position >= mDatas.size() - layoutManager.getSpanCount() || !rv.canScrollVertically(1)) {//滑到底部了if (canLoadMore) {XLog.tag("bqt_red").i("加载更多 "+position+" "+rv.canScrollVertically(1));canLoadMore = false;doRequest();}break;}}}}
});

利用 lastVisibleItemPosition 判断【不靠谱】

简单判断

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

当屏幕中最后一个子项 lastVisibleItemPosition 等于所有子项个数 totalItemCount - 1,那么RecyclerView就到达了底部。
但是,如果 totalItemCount 等于1,并且这个item的高度比屏幕还要高时,我们可以发现这个item没完全显示出来就已经被判断为拉到底部。

利用 computeVerticalScrollRange 等判断【不靠谱】

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

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

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

利用 canScrollVertically(direction) 判断【比较靠谱】

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

/*** Check if this view can be scrolled vertically in a certain direction.** @param direction Negative to check scrolling up, positive to check scrolling down.* @return true if this view can be scrolled in the specified direction, false otherwise.*/
public boolean canScrollVertically(int direction) {final int offset = computeVerticalScrollOffset();final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();if (range == 0) return false;if (direction < 0) {return offset > 0;} else {return offset < range - 1;}
}

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

利用 LinearLayoutManager 来判断【垃圾】

这种方法其实是比较呆板的,就是利用LinearLayoutManager的几个方法算出已经滑过的子项的距离、屏幕的高度、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 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;
}

  • 其他逻辑
public static int getHeaderHeight(RecyclerView recyclerView) {int headerCildHeight = 0;LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();int firstHeaderPos = layoutManager.findFirstCompletelyVisibleItemPosition();View headerCild = layoutManager.findViewByPosition(firstHeaderPos);if (headerCild != null) {RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) headerCild.getLayoutParams();headerCildHeight = headerCild.getHeight() + params.topMargin + params.bottomMargin;}return headerCildHeight;
}

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;
}

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

2017.06.23

RecyclerView 判断滑到底部 顶部 预加载 更多 分页 MD相关推荐

  1. 底部点击加载更多功能的简单实现

    底部点击加载更多功能的简单实现 ​ 主要思路是:后台将数据按10个一页进行处理,前端请求的时候传递的分页参数就是页数.从主页选择一个类型去到列表页,会先从后端请求10条数据渲染到页面上.点击加载更多的 ...

  2. 移动端网页如何实现加载更多分页

    移动端网页如何实现加载更多分页 实例代码如下 jq $(window).scroll(function(){ var scrollTop = $(this).scrollTop(); //滚动条距离顶 ...

  3. 采用SwipeFreshLayout+Recyclerview实现下拉刷新和上拉加载更多以及CoordinatorLayout的引入

    之前都是采用PullToRefresh进行下拉刷新和下拉加载,现在采用谷歌自己的控件SwipeFreshLayout,配合Recyclerview来实现这一效果.使用SwipeRefreshLayou ...

  4. android 官方上拉,手把手教你实现RecyclerView的下拉刷新和上拉加载更多

    纵观多数App,下拉刷新和上拉加载更多是很常见的功能,但是谷歌官方只有一个SwipeRefreshLayout用来下拉刷新,上拉加载更多还要自己做. 基于RecyclerView简单封装了这两个操作, ...

  5. vue滚动到底部,自动加载更多

    原文地址:vue 实现滚动到页面底部开始加载更多 - will很忙 - 博客园 vue 实现滚动到页面底部开始加载更多 1 scrollTop 页面滚动的高度, 1 clientHeight 可视区域 ...

  6. 一个到顶部自动加载更多的ListView

    为什么80%的码农都做不了架构师?>>>    一个可以到顶自动加载更多的ListView,实现该控件的目的是用于im聊天页面场景,一些第三方实现的下拉加载更多也可以实现类似功能,但 ...

  7. 保姆式RecyclerView下拉刷新、上拉加载更多Kotlin

    网络图片加载显示.保存.更新到图库.分享到微信 开发步骤 思路步骤 安卓10以上:下载图片到私有空间(沙盒),从私有空间复制到公共空间,然后通知相册更新 直接定义好下载的图片路径 通过glide框架下 ...

  8. RecycviewView加载更多和预加载

    一.Recycleview的上拉加载更多 mRecyclerview.addOnScrollListener(mOnScrollListener);RecyclerView.OnScrollListe ...

  9. html5到底部自动加载,列表滚动到底部自动加载更多

    列表滚动到底部自动加载更多 在移动端,经常会用到列表滚动到底部,拉一下加载更多,或者点一下加载更多等等,今天我说说我的一个实现的思路. 通过监听列表的滚动时间,当用户滚动到列表的底部,并停留一小段时间 ...

  10. php下拉上滑分页,Flutter实现下拉刷新 上拉分页加载更多

    一.Flutter实现下拉刷新和上拉分页加载更多 在Flutter官方sdk中给我们提供了下拉刷新的组件RefreshIndicator.但是没有提供上拉分页加载更多的组件.但是在Flutter Li ...

最新文章

  1. setTimeOut函数和setInterval函数
  2. Eclipse开发C/C++之使用技巧小结,写给新手
  3. pytorch 使用cpu_想读读PyTorch底层代码?这份内核机制简介送给你
  4. 判断字符串中是否包含中文
  5. 基于MaxCompute搭建社交好友推荐系统
  6. HBase环境搭建60010端口无法访问问题解决方案
  7. 95-18-015-配置-AbstractBootstrapConfig
  8. zookeeper配置与使用
  9. 今天,很高兴!我成为了园子里的一份子!
  10. 用JavaScript编写COM组件的步骤
  11. 苹果Mac版 PhotoShop 2021 自动上色功能?
  12. python学习笔记2---内置函数
  13. 序列号Serial Number管理
  14. sxe增加服务器,sXe Injected服务端使用说明
  15. eclipse中 错误: 找不到或无法加载主类 f.B
  16. python攻击局域网电脑_局域网攻击
  17. docker mysql redis 镜像详解
  18. Java——博主的学习路线
  19. 虚拟机云服务器6.0教程pdf,虚拟机云服务器6.0教程pdf
  20. 不小心删除了360浏览器里收藏夹的内容,怎么恢复

热门文章

  1. jQuery.param() 函数详解
  2. 主成分分析 PCA算法原理
  3. Zend Studio IDE使用yii framework框架无代码提示的解决方法
  4. 内存映射之fixmap(early_fixmap_init)
  5. linux内核分析与应用 -- 并发(上)
  6. Linux内存管理之vmalloc与low_memory
  7. Sofia-SIP辅助文档三 - 编码指南
  8. python md5算法调用与hashlib模块
  9. linux查看进程占用内存与ps命令
  10. vue 改变组件data_为什么vue组件中data必须用函数表达?