【发布时间】:2016-07-13 21:32:23
【问题描述】:
RecyclerView 有一个 InfiniteScrollListener 并且在该侦听器内部,在OnScrolled() 方法中,我计算可见项和总项数以检查是否应加载新项。当 totalItemCount 和 visibleItemCount 相同时,会导致加载无限循环。听众与我的其他 RecyclerViews 完美地工作,它没有 CoordinatorLayout 或 NestedScrollView 作为父母。
我想保留这种结构,因为客户不会接受更改。
我在一个 Activity 中有一个片段,它的布局是这样的
CoordinatorLayout{
NestedScrollView{
RecyclerView{
}
}
}
sdk 版本
compileSdkVersion 24
buildToolsVersion "23.0.3"
...
minSdkVersion 21
targetSdkVersion 24
fragment_profile.xml 作为父布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay"
app:layout_behavior="com.paxotic.paxira.util.behavior.AppBarFlingBehavior">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height_small"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
app:layout_collapseMode="parallax">
<ImageView
android:id="@+id/img_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.5"
android:scaleType="centerCrop"
tools:src="@drawable/bg_greeting_activity" />
</RelativeLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include
layout="@layout/activity_profile_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
... />
</android.support.design.widget.CoordinatorLayout>
fragment_profile.xml 作为子布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
...
<android.support.v7.widget.RecyclerView
android:id="@+id/feedRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="@dimen/spacing_normal"
tools:listitem="@layout/list_item_activity" />
...
</android.support.v4.widget.NestedScrollView>
ProfileFragment.java:相关函数
private void init() {
feedAdapter = new FeedAdapter(host);
feedAdapter.setHasStableIds(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(host);
feedRecycler.setLayoutManager(layoutManager);
feedRecycler.setNestedScrollingEnabled(false);
feedRecycler.setHasFixedSize(true);
feedRecycler.setAdapter(feedAdapter);
infiniteScrollListener = new InfiniteScrollListener(host, layoutManager) {
@Override
public void onLoadMore(int pageIndex) {
if (!feedAdapter.isLoading) {
loadFeed(pageIndex);
}
}
};
feedRecycler.addOnScrollListener(infiniteScrollListener);
}
InfiniteScrollListener.java
public abstract class InfiniteScrollListener extends RecyclerView.OnScrollListener {
private int previousTotal = 0; // The total number of items in the dataset after the last load
private boolean loading = false; // True if we are still waiting for the last set of data to load.
private static final int VISIBLE_THRESHOLD = 5; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;
private int current_page = 0;
private int loadingItemCount;
private LinearLayoutManager mLinearLayoutManager;
public InfiniteScrollListener(Context context, LinearLayoutManager linearLayoutManager) {
this.mLinearLayoutManager = linearLayoutManager;
loadingItemCount = context.getResources().getInteger(R.integer.feed_pull_item_count);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy < 0) return; // check for scroll down
visibleItemCount = mLinearLayoutManager.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
synchronized (this) {
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + VISIBLE_THRESHOLD)) {
// End has been reached, Do something
current_page++;
onLoadMore(current_page);
loading = true;
}
}
}
public abstract void onLoadMore(int current_page);
public void setLoading(boolean loading) {
this.loading = loading;
}
@Override
public void onScrollStateChanged(RecyclerView view, int scrollState) {
// Don't take any action on changed
}
}
【问题讨论】:
-
嘿,你找到解决方案了吗?我有同样的问题..
-
我找到了核心问题,不幸的是@DarkLeonhart没有解决方案。问题是 NestedScrollView 的行为是因为它在屏幕上可见,所以它会绘制所有子项,并且 RecyclerView 返回所有可见的子项,这些子项是它的适配器拥有的所有项目,因此,getChildCount() 和 getItemCount() 为我们提供了相同的值。我现在已经改变了我的用户界面。我只用 RecyclerView 加载了 10 个项目,并且有一个按钮可以通向另一个无限滚动的活动。
-
@DarkLeonhart 你找到解决方案了吗?
-
as @dgngulcan 问题是当 RecyclreView 位于 NestedScrollView 内时,因此 RecyclerView 的滚动侦听器似乎没有任何影响。相反,我使用了基于stackoverflow.com/a/38570106/2178568 的 NestedScrollView 的滚动监听器
标签: java android infinite-scroll