判断RecyclerView是否滚动到底部

转:http://www.jianshu.com/p/c138055af5d2

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

public static boolean isVisBottom(RecyclerView recyclerView){  
  LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();  
  //屏幕中最后一个可见子项的position
  int 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;
}
posted @ 2017-04-21 14:35  jdhdevelop  阅读(13631)  评论(0编辑  收藏  举报