gpt4 book ai didi

android - 当列表中的项目最小然后屏幕大小时,无尽滚动 RecyclerView 不工作

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:03:17 24 4
gpt4 key购买 nike

我已经使用 Recycler View 成功实现了无限滚动。我正在使用 this代码,这很完美,但以下情况除外

情况 1:当列表有 2 个小于屏幕尺寸的项目时,它看起来像 OnLoadMore 再次调用,因为它发现自己到达列表的末尾

我在做什么:我从 1 个 fragment 获取列表,然后将此列表发送到另一个 fragment ,在该 fragment 中有一个带有 onScroll listner 的 RecyclerView,如下所示:

recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager) {
@Override
public void onLoadMore(int page, int totalItemsCount) {
// do something...

currentVisiblePosition = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
pageNumber = pageNumber + 1;
CallingMyApi();

}
});

困惑:

  • 我的 RecyclerView 添加滚动监听器,当 fragment 被初始化时第一次运行。因为没有执行滚动。
  • 如果有较少的项目,比如说 2,它总是在 fragment 初始化时运行,如果有很多项目,OnLoadMore 方法不会运行。

所以我可以猜测这是由于 ListView 中的项目较少导致的问题如何控制请帮助我??

更新一:我的 fragment 代码

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);

mAdapter = new EnrollmentSearchAdapter(getActivity(), parentList);

rvSearchEnrollments.addOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager) {
@Override
public void onLoadMore(int page, int totalItemsCount) {
// do something...

if(parentList!=null && parentList.size()>3) { // just checking my own that 3 items should not be minimum to screen size , where as here it should be more flexible solution
currentVisiblePosition = ((LinearLayoutManager) rvSearchEnrollments.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
pageNumber = pageNumber + 1;
SearchSundaySchoolParentsCouples searchSundaySchoolParentsCouples = new SearchSundaySchoolParentsCouples(keyword, 20, pageNumber, getActivity());
searchSundaySchoolParentsCouples.execute();
}
}
});

rvSearchEnrollments.addItemDecoration(new SimpleDividerItemDecoration(getActivity()));

rvSearchEnrollments.setAdapter(mAdapter);


}

最佳答案

使用 EndlessRecyclerViewScrollListener OnScrollListener 子类(来自流行的 Gist)。当列表中的项目最小然后屏幕大小时,您需要更改一些内容才能使无休止的滚动 RecyclerView 正常工作。

这是您需要添加到 EndlessRecyclerViewScrollListener 的内容类:

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{
super.onScrollStateChanged(recyclerView, newState);
// Don't do any work until after the ScrollEvent has ended, so do the following check.
if (newState == RecyclerView.SCROLL_STATE_IDLE)
{
// supply a positive number to recyclerView.canScrollVertically(int direction) to check if scrolling down.
boolean canScrollDownMore = recyclerView.canScrollVertically(1);
// If recyclerView.canScrollVertically(1) returns false it means you're at the end of the list.
if (!canScrollDownMore)
{
//call the overridden onScrolled() method in our EndlessRecyclerViewScrollListener class.
// supply any positive number to the third argument to indicate that we've scrolled downward.
onScrolled(recyclerView, 0, 1);
}
}
}

说明: 我们需要实现 onScrollStateChanged() 方法,因为 onScrolled() 在结束时不会被调用列表,或者至少当列表中的项目小于屏幕大小时它不会被调用。

这是包含您需要的更新的整个 EndlessRecyclerViewScrollListener 类:

public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener
{
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;

private RecyclerView.LayoutManager layoutManager;

public void setLayoutManager(RecyclerView.LayoutManager layoutManager)
{
this.layoutManager = layoutManager;
}

public RecyclerView.LayoutManager getLayoutManager()
{
return layoutManager;
}

public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager)
{
this.layoutManager = layoutManager;
}

public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager, int visibleThreshold)
{
this.layoutManager = layoutManager;
this.visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}

public EndlessRecyclerViewScrollListener(
StaggeredGridLayoutManager layoutManager,
int visibleThreshold)
{
this.layoutManager = layoutManager;
this.visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}

public int getLastVisibleItem(int[] lastVisibleItemPositions)
{
int maxSize = 0;
for (int i = 0; i < lastVisibleItemPositions.length; i++)
{
if (i == 0)
{
maxSize = lastVisibleItemPositions[i];
}
else if (lastVisibleItemPositions[i] > maxSize)
{
maxSize = lastVisibleItemPositions[i];
}
}
return maxSize;
}

// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScrolled(RecyclerView view, int dx, int dy)
{
if (dy < 1)
{
// don't do anything when scrolling up.
return;
}
int lastVisibleItemPosition = 0;
int totalItemCount = layoutManager.getItemCount();

if (layoutManager instanceof StaggeredGridLayoutManager)
{
int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null);
// get maximum element within the list
lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
}
else if (layoutManager instanceof GridLayoutManager)
{
lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
}
else if (layoutManager instanceof LinearLayoutManager)
{
lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
}

// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount)
{
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0)
{
this.loading = true;
}
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount >= previousTotalItemCount))
{
loading = false;
previousTotalItemCount = totalItemCount;
}

// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount)
{
currentPage++;
onLoadMore(currentPage, totalItemCount, view);
loading = true;
}
}

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE)
{
// supply a positive number to recyclerView.canScrollVertically(int direction) to check if scrolling down.
boolean canScrollDownMore = recyclerView.canScrollVertically(1);
// If recyclerView.canScrollVertically(1) returns false it means you're at the end of the list.
if (!canScrollDownMore)
{
onScrolled(recyclerView, 0, 1);
}
}
}

// Call this method whenever performing new searches on in onRefresh() if using SwipeRefresh
public void resetState()
{
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = 0;
this.loading = true;
}

// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);

}

用法简要示例: ( more info here )

    public class MainActivity extends Activity {
// Store a member variable for the listener
private EndlessRecyclerViewScrollListener scrollListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
// Configure the RecyclerView
RecyclerView rvItems = (RecyclerView) findViewById(R.id.rvContacts);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
rvItems.setLayoutManager(linearLayoutManager);
// Retain an instance so that you can call `resetState()` for fresh searches
scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) {
@Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to the bottom of the list
loadNextDataFromApi(page);
}
};
// Adds the scroll listener to RecyclerView
rvItems.addOnScrollListener(scrollListener);
}

// Append the next page of data into the adapter
// This method probably sends out a network request and appends new data items to your adapter.
public void loadNextDataFromApi(int offset) {
// Send an API request to retrieve appropriate paginated data
// --> Send the request including an offset value (i.e `page`) as a query parameter.
// --> Deserialize and construct new model objects from the API response
// --> Append the new data objects to the existing set of items inside the array of items
// --> Notify the adapter of the new items made with `notifyItemRangeInserted()`
}
}

您可能需要稍微修改一下才能使其在您的场景中正常工作,但提供的代码是一个很好的起点。

关于android - 当列表中的项目最小然后屏幕大小时,无尽滚动 RecyclerView 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39077218/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com