版權聲明:本文源自簡書tianma谢床,轉載請務必注明出處: http://www.reibang.com/p/e893e4c569fb
最近想動手實現(xiàn) RecyclerView
的“自動加載更多”功能,即當 RecyclerView
滑動到底部時,執(zhí)行加載更多操作。這里的關鍵在于,需要監(jiān)聽RecyclerView是否滑動到底部。
分析
RecyclerView
有 addOnScrollListener(OnScrollListener)
方法,可以為 RecyclerView
添加滾動監(jiān)聽合蔽,其中 OnScrollListener
有兩個回調函數(shù):
- onScrollStateChanges(RecyclerView recyclerView, int newState): 在
RecyclerView
的滾動狀態(tài)發(fā)生改變時回調 - onScrolled(RecyclerView recyclerView, int dx, int dy): 在
RecyclerView
滾動時回調
在 OnScrollListener
回調中,可以獲取RecyclerView的滾動狀態(tài)介返,我們只需要通過繼承 OnScrollListener
并復寫上面的兩個回調函數(shù)拴事,便可以實現(xiàn)對 RecyclerView
滑動到底部的監(jiān)聽。
實現(xiàn)
我們先定義一個回調接口 BottomListener
用以監(jiān)聽控件是否滾動到底部:
public interface BottomListener {
/**
* 滑動到底部時回調
*/
void onScrollToBottom();
}
然后圣蝎,我們繼承 RecyclerView.OnScrollListener
和實現(xiàn) BottomListener
:
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
/**
* 實現(xiàn)了RecyclerView滾動到底部監(jiān)聽的OnScrollListener
*/
public class RecyclerViewScrollListener extends RecyclerView.OnScrollListener implements BottomListener {
// 最后幾個完全可見項的位置(瀑布式布局會出現(xiàn)這種情況)
private int[] lastCompletelyVisiblePositions;
// 最后一個完全可見項的位置
private int lastCompletelyVisibleItemPosition;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
// 找到最后一個完全可見項的位置
if (layoutManager instanceof StaggeredGridLayoutManager) {
StaggeredGridLayoutManager manager = (StaggeredGridLayoutManager) layoutManager;
if (lastCompletelyVisiblePositions == null) {
lastCompletelyVisiblePositions = new int[manager.getSpanCount()];
}
manager.findLastCompletelyVisibleItemPositions(lastCompletelyVisiblePositions);
lastCompletelyVisibleItemPosition = getMaxPosition(lastCompletelyVisiblePositions);
} else if (layoutManager instanceof GridLayoutManager) {
lastCompletelyVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastCompletelyVisibleItemPosition();
} else if (layoutManager instanceof LinearLayoutManager) {
lastCompletelyVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastCompletelyVisibleItemPosition();
} else {
throw new RuntimeException("Unsupported LayoutManager.");
}
}
private int getMaxPosition(int[] positions) {
int max = positions[0];
for (int i = 1; i < positions.length; i++) {
if (positions[i] > max) {
max = positions[i];
}
}
return max;
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
// 通過比對 最后完全可見項位置 和 總條目數(shù)刃宵,來判斷是否滑動到底部
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (visibleItemCount > 0 && lastCompletelyVisibleItemPosition >= totalItemCount - 1) {
onScrollToBottom();
}
}
}
@Override
public void onScrollToBottom() {
}
}
上述大體思路就是: 找到 "最后完全可見項的位置(lastCompletelyVisibleItemPosition)",通過比較 lastCompletelyVisibleItemPosition 是否是 RecyclerView
最后一項徘公,來判斷是否滑動到底部牲证。
在 RecyclerView
上應用加載更多:
recyclerView.addOnScrollListener(new RecyclerViewScrollListener() {
@Override
public void onScrollToBottom() {
// 加載更多
doLoadMore();
}
});
// ...
private void doLoadMore() {
// TODO load more
}
參考鏈接:
通過重寫OnScrollListener來監(jiān)聽RecyclerView是否滑動到底部
特別注意
個人認為上面的參考鏈接中給出的方案是有待商榷的,原博主計算的是 "最后一個可見項的位置(lastVisibleItemPosition)"关面,而本文中計算的是 "最后一個完全可見項的位置(lastCompletelyVisibleItemPosition)" , 很明顯 RecyclerView
列表中最后一個元素可見的時候坦袍,RecyclerView
并不一定滑動到最底部了。當然了等太,具體采取哪種方案捂齐,需要根據實際需求來確定。