RecyclerView 判斷滑到底/頂部的方法
阿新 • • 發佈:2017-06-07
mode sbo style osi set vertica 條件 pos cif 判斷RecyclerView到達底部的幾種方法
算出一個子項的高度
雖然這種方法看上去比較呆板的同時考慮不很周全,但這種方法可以對RecylerView的LinearLayoutManager有深一步的理解!
null
項目中的案例
mRvChat.addOnScrollListener(new RecyclerView.OnScrollListener() {
private int minLeftItemCount=10;//剩余多少條時開始加載更多
@Override
public 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("【加載更多數據】");
}
}
});
利用 lastVisibleItemPosition 判斷
簡單判斷當屏幕中最後一個子項 lastVisibleItemPosition 等於所有子項個數 totalItemCount - 1,那麽RecyclerView就到達了底部。但是,如果 totalItemCount 等於1,並且這個item的高度比屏幕還要高時,我們可以發現這個item沒完全顯示出來就已經被判斷為拉到底部。
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;
}
}
利用 computeVerticalScrollRange 等判斷
這種方法原理其實很簡單,而且也是View自帶的方法這種方法經過測試,暫時還沒發現有bug,而且它用的是View自帶的方法,所以個人覺得比較靠譜。
public static boolean isSlideToBottom(RecyclerView recyclerView) {
return recyclerView != null
&& recyclerView.computeVerticalScrollExtent()//當前屏幕顯示區域的高度
+ recyclerView.computeVerticalScrollOffset()//當前屏幕之前滑過的距離
>= recyclerView.computeVerticalScrollRange();//整個View控件的高度
}
利用 canScrollVertically(direction) 判斷
這種方法更簡單,就通過簡單的調用方法,就可以得到你想要的結果。這種方法與第二種方法其實是同一種方法,我們看看 canScrollVertically 的源碼:canScrollVertically(1)的值表示是否能向上滾動,true表示能滾動,false表示已經滾動到底部canScrollVertically(-1)的值表示是否能向下滾動,true表示能滾動,false表示已經滾動到頂部
/**
* 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;
}
}
利用 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有深一步的理解!
null
RecyclerView 判斷滑到底/頂部的方法