使用 staggeredGridLayoutManager 和 recyclerView 进行分页
Posted
技术标签:
【中文标题】使用 staggeredGridLayoutManager 和 recyclerView 进行分页【英文标题】:Pagination with staggeredGridLayoutManager and recyclerView 【发布时间】:2018-12-21 19:19:50 【问题描述】:您好,我需要使用 staggeredGridLayoutManager 使用 recyclerview 进行无限滚动(分页)。分页正在工作,但问题是 onLoadMore()
函数在滚动时被调用了很多次导致问题,这是我的代码:
newSearchAdapter = new NewSearchAdapter(getActivity(), gridData);
StaggeredGridLayoutManager mLayoutManager;
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
rv_NewProfilesGrid.setLayoutManager(mLayoutManager);
rv_NewProfilesGrid.setAdapter(newSearchAdapter);
rv_NewProfilesGrid.addOnScrollListener(new EndlessRecyclerOnScrollListenerStaggeredLayoutmanager(mLayoutManager)
@Override
public void onLoadMore(int current_page)
//calling the api
);
这是我的滚动监听器
我认为这里的问题在于 getFirstVisibleItems()
函数,因为使用 GridLayoutManger 或 LinearLayoutManager 它返回一个整数,但使用 StaggeredLayout 它返回一个 int 数组,所以我做了以下操作:
public abstract class EndlessRecyclerOnScrollListenerStaggeredLayoutmanager extends RecyclerView.OnScrollListener
public static String TAG = EndlessRecyclerOnScrollListenerStaggeredLayoutmanager.class.getSimpleName();
private int scrolledDistance = 0;
private boolean controlsVisible = false;
private boolean loading = true; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
public static boolean loadOneTime = false;
private int pastVisibleItems, visibleItemCount, totalItemCount,previousTotal;
private int current_page = 1;
private StaggeredGridLayoutManager mStaggeredGridLayoutManager;
public EndlessRecyclerOnScrollListenerStaggeredLayoutmanager(StaggeredGridLayoutManager staggeredGridLayoutManager)
this.mStaggeredGridLayoutManager = staggeredGridLayoutManager;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mStaggeredGridLayoutManager.getItemCount();
int[] firstVisibleItems = null;
firstVisibleItems = mStaggeredGridLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
if (firstVisibleItems != null && firstVisibleItems.length > 0)
pastVisibleItems = firstVisibleItems[0];
if (loading)
if ((visibleItemCount + pastVisibleItems) >= totalItemCount)
loading = false;
previousTotal = totalItemCount;
if (!loading && (totalItemCount - visibleItemCount)
<= (pastVisibleItems + visibleThreshold))
// End has been reached
// Do something
current_page++;
loadOneTime=false;
onLoadMore(current_page);
loading = true;
if (scrolledDistance > 1 && controlsVisible)
controlsVisible = false;
scrolledDistance = 0;
else if (scrolledDistance < -1 && !controlsVisible)
controlsVisible = true;
scrolledDistance = 0;
if ((controlsVisible && dy > 0) || (!controlsVisible && dy < 0))
scrolledDistance += dy;
public abstract void onLoadMore(int current_page);
【问题讨论】:
我遇到了同样的问题,但是使用了 Paging 库并遇到了这个 github gist gist.github.com/pratikbutani/dc6b963aa12200b3ad88aecd0d103872 我认为它会解决你的问题 【参考方案1】:试试这个。我从堆栈溢出答案中借用它并借用另一个答案并结合它们我终于解决了它。
import android.util.Log
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
abstract class PaginationScrollListener constructor() :
RecyclerView.OnScrollListener()
private lateinit var mLayoutManager: RecyclerView.LayoutManager
constructor(layoutManager: GridLayoutManager) : this()
this.mLayoutManager = layoutManager
constructor(layoutManager: StaggeredGridLayoutManager) : this()
this.mLayoutManager = layoutManager
constructor(layoutManager: LinearLayoutManager) : this()
this.mLayoutManager = layoutManager
/*
Method gets callback when user scroll the search list
*/
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int)
super.onScrolled(recyclerView, dx, dy)
val visibleItemCount = mLayoutManager.childCount
val totalItemCount = mLayoutManager.itemCount
var firstVisibleItemPosition = 0
when (mLayoutManager)
is StaggeredGridLayoutManager ->
val firstVisibleItemPositions =
(mLayoutManager as StaggeredGridLayoutManager).findFirstVisibleItemPositions(null)
// get maximum element within the list
firstVisibleItemPosition = firstVisibleItemPositions[0]
is GridLayoutManager ->
firstVisibleItemPosition =
(mLayoutManager as GridLayoutManager).findFirstVisibleItemPosition()
is LinearLayoutManager ->
firstVisibleItemPosition =
(mLayoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
if (!isLoading && !isLastPage)
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount
&& firstVisibleItemPosition >= 0
)
Log.i(TAG, "Loading more items")
loadMoreItems()
protected abstract fun loadMoreItems()
abstract val isLastPage: Boolean
abstract val isLoading: Boolean
companion object
private val TAG = PaginationScrollListener::class.java.simpleName
并以这种方式在您的回收站视图中使用它
rvCategoryProducts.addOnScrollListener(object :
PaginationScrollListener(layoutManager)
override fun loadMoreItems()
vm.isLoading = true
vm.currentPage++
GlobalScope.launch
vm.getCategoryProductByCatId(vm.id, vm.currentPage)
override val isLastPage: Boolean
get() = vm.isLastPage
override val isLoading: Boolean
get() = vm.isLoading
)
【讨论】:
以上是关于使用 staggeredGridLayoutManager 和 recyclerView 进行分页的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)