You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NestedScrollView中实现RecyclerView的无限滚动?

解决NestedScrollView嵌套RecyclerView时的视图回收问题

我最近碰到个头疼的问题:单屏里塞了两个RecyclerView,条目太多导致屏幕装不下,于是把RecyclerView放到NestedScrollView里想实现滚动。结果倒好,RecyclerView直接一次性加载所有条目,完全不做视图回收,性能拉胯得不行。

我试过两种方法都没效果:一是给RecyclerView加app:layout_behavior="@string/appbar_scrolling_view_behavior",二是调用mRecyclerView.setNestedScrollingEnabled(false),都没解决问题。有没有靠谱的解决方案?

我的代码

Java代码

myDataset = new ArrayList<>();
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.map_recycler_view);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(mcontext);
mLayoutManager.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter(this);
mAdapter.setLinearLayoutManager(mLayoutManager);
mAdapter.setRecyclerView(mRecyclerView);
mRecyclerView.setAdapter(mAdapter);

XML代码

<android.support.v4.widget.NestedScrollView
    android:id="@+id/nestedScrollView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="180dp">
            <fragment
                android:id="@+id/googleMap"
                android:name="com.google.android.gms.maps.SupportMapFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </FrameLayout>
        <!-- 第一个RecyclerView -->
        <android.support.v7.widget.RecyclerView
            android:id="@+id/map_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <!-- 第二个RecyclerView -->
        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</android.support.v4.widget.NestedScrollView>

可行解决方案

方案一:自定义LinearLayoutManager重写测量逻辑

NestedScrollView会让RecyclerView的高度被强制测量为wrap_content,导致它加载所有子项。我们可以重写LinearLayoutManager的测量方法,让它只计算可见区域的高度:

public class CustomLinearLayoutManager extends LinearLayoutManager {
    public CustomLinearLayoutManager(Context context) {
        super(context);
    }

    public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    public CustomLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
        // 自定义高度测量规则,让RecyclerView只测量可见条目
        int heightSpecCustom = View.MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
        super.onMeasure(recycler, state, widthSpec, heightSpecCustom);
        ViewGroup.LayoutParams params = recyclerView.getLayoutParams();
        params.height = getMeasuredHeight();
    }
}

然后替换原来的LinearLayoutManager:

CustomLinearLayoutManager mLayoutManager = new CustomLinearLayoutManager(mcontext);
mRecyclerView.setLayoutManager(mLayoutManager);
// 同时关闭RecyclerView自身的嵌套滚动
mRecyclerView.setNestedScrollingEnabled(false);

方案二:用ConstraintLayout替代NestedScrollView(推荐)

如果你的布局支持,直接用ConstraintLayout来布局两个RecyclerView,让它们各自占据剩余空间,完全不需要嵌套滚动,性能更好:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/map_container"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        app:layout_constraintTop_toTopOf="parent"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/first_recycler"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/map_container"
        app:layout_constraintBottom_toTopOf="@id/second_recycler"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/second_recycler"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/first_recycler"
        app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

这种方式下两个RecyclerView各自独立处理滚动和视图回收,不会出现一次性加载所有条目的问题。

内容的提问来源于stack exchange,提问作者Jshin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:50:13