ScrollView 中的 RecyclerView 滑动不流畅

192

我的应用程序中,我使用了一个 ScrollView 包含一个基于内容高度利用这个库RecyclerView。滚动是正常的,但当我在 RecyclerView 上滚动时,它不够流畅。当我在 ScrollView 上滚动时,滚动是流畅的。

我使用的定义 RecyclerView 的代码如下:

LinearLayoutManager friendsLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext(), android.support.v7.widget.LinearLayoutManager.VERTICAL, false);
mFriendsListView.setLayoutManager(friendsLayoutManager);
mFriendsListView.addItemDecoration(new DividerItemDecoration(getActivity().getApplicationContext(), null));

ScrollView 中的 RecyclerView

<android.support.v7.widget.RecyclerView
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    android:id="@+id/friendsList"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

这个解决方案对我有用: https://dev59.com/i47ea4cB1Zd3GeqPEa0b#32390370 谢谢 - Houssin Boulla
1
@tahaDev,请详细说明您的情况中到底有什么问题。此外,似乎没有提供的解决方案适用于您的情况,是这样吗? - Pravin Divraniya
使用androidx.constraintlayout.widget.ConstraintLayout,它可以解决你的问题,而无需进行任何复杂的实现。 - Saswata
18个回答

399

尝试执行以下操作:

RecyclerView v = (RecyclerView) findViewById(...);
v.setNestedScrollingEnabled(false);

作为另一种选择,您可以使用支持设计库来修改布局。我猜您当前的布局类似于:

<ScrollView >
   <LinearLayout >

       <View > <!-- upper content -->
       <RecyclerView > <!-- with custom layoutmanager -->

   </LinearLayout >
</ScrollView >

你可以修改为:

<CoordinatorLayout >

    <AppBarLayout >
        <CollapsingToolbarLayout >
             <!-- with your content, and layout_scrollFlags="scroll" -->
        </CollapsingToolbarLayout >
    </AppBarLayout >

    <RecyclerView > <!-- with standard layoutManager -->

</CoordinatorLayout >

然而,这是一条更漫长的路线,如果您可以接受自定义线性布局管理器,那么只需在回收站视图上禁用嵌套滚动即可。

编辑(2016年4月3日)

支持库的v 23.2版本现在包括所有默认LayoutManager中的“wrap content”特性。我没有测试过,但您可能更喜欢它,而不是使用那个库。

<ScrollView >
   <LinearLayout >

       <View > <!-- upper content -->
       <RecyclerView > <!-- with wrap_content -->

   </LinearLayout >
</ScrollView >

17
补充一下这个答案:仅当我将 ScrollView 替换为 NestedScrollView 时,调用 setNestedScrollingEnabled(false) 才有效。 - Richard Le Mesurier
11
对我来说,setNestedScrollingEnabled(false) 使得我的 RecyclerViewScrollView 中拥有了流畅的滚动 - 谢谢!但我仍然不理解为什么会起作用...?将嵌套滚动设置为 false 究竟意味着什么? - Micro
33
请注意,android:nestedScrollingEnabled="false" 仅适用于 API 21+,但 <21 可以使用 v.setNestedScrollingEnabled(false) - Eric B.
3
供以后参考,如果有人在ScrollView中遇到只会出现在Marshmallow / Nougat(API 23,24)设备上的RecyclerView wrap_content问题,请查看我的解决方法,网址为https://dev59.com/il4d5IYBdhLWcg3wLf_P#38995399。请注意,不要改变原文的意思。 - Hossain Khan
2
我现在遇到的这种解决方案的缺点是,RecyclerView将无法在其onScrollListener中接收事件。我需要这个功能,因为当Recycler中只有一定数量的项目时,我想获取更多的数据。 - Daniel W.
显示剩余9条评论

88

我只需要使用这个:

mMyRecyclerView.setNestedScrollingEnabled(false);

在我的onCreateView()方法中。

非常感谢!


30
你可以使用以下方法:
在你的recyclerView xml文件中添加这行代码:
android:nestedScrollingEnabled="false"

或者在Java代码中:

RecyclerView.setNestedScrollingEnabled(false);
希望这有所帮助。

10
需要 API 21 或更高版本。 - Muhammad Riyaz

11

你可以尝试使用XML和编程两种方式。但是问题在于(API 21以下)使用XML进行设置可能会失败。因此,最好在您的Activity / Fragment中以编程方式设置它。

XML代码:

<android.support.v7.widget.RecyclerView
      android:id="@+id/recycleView"
      android:layout_width="match_parent"
      android:visibility="gone"
      android:nestedScrollingEnabled="false"
      android:layout_height="wrap_content"
      android:layout_below="@+id/linearLayoutBottomText" /> 

程序化地:

 recycleView = (RecyclerView) findViewById(R.id.recycleView);
 recycleView.setNestedScrollingEnabled(false);

7

使用嵌套滚动视图而不是滚动视图,解决了我的问题。

<LinearLayout> <!--Main Layout -->
   <android.support.v4.widget.NestedScrollView>
     <LinearLayout > <!--Nested Scoll View enclosing Layout -->`

       <View > <!-- upper content --> 
       <RecyclerView >


     </LinearLayout > 
   </android.support.v4.widget.NestedScrollView>
</LinearLayout>

5
使用NestedScrollView替换ScrollView,可以实现平滑滚动到底部。

5

我曾经遇到过类似的问题(尝试创建类似Google PlayStore设计的嵌套RecyclerViews)。最好的处理方法是通过子类化子RecyclerViews并覆盖'onInterceptTouchEvent'和'onTouchEvent'方法。这样,您可以完全控制这些事件的行为,并实现滚动。


5

这里所有的答案都是一样的。我已经使用了每个人建议的方法。然后我发现NestedScrollView比ScrollView更快,因此

使用NestedScrollView。

<androidx.core.widget.NestedScrollView

与其

<ScrollView

然后像往常一样使用它

recycleView.setNestedScrollingEnabled(false);

3

所有答案的概要(优点和缺点)

对于单个RecyclerView

您可以在Coordinator layout中使用它。

优点 - 它不会加载整个RecyclerView项目。因此,加载流畅。

缺点 - 您不能在Coordinator layout中加载两个RecyclerView - 这会产生滚动问题。

参考 - https://dev59.com/LlwY5IYBdhLWcg3wATpt#33143512

对于多个最小行数的RecyclerView

您可以在NestedScrollView内加载它们。

优点 - 它将平稳滚动。

缺点 - 它会加载RecyclerView的所有行,因此您的活动会有延迟。

参考 - https://dev59.com/LlwY5IYBdhLWcg3wATpt#33143512

对于具有大行数(超过100个)的多个RecyclerView

您必须使用RecyclerView。

优点 - 平稳滚动,流畅加载

缺点 - 您需要编写更多的代码和逻辑

使用多个视图持有器在主RecyclerView中加载每个RecyclerView

例如:

MainRecyclerview

-ChildRecyclerview1 (ViewHolder1)

-ChildRecyclerview2 (ViewHolder2)

-ChildRecyclerview3 (ViewHolder3) 

-Any other layout   (ViewHolder4)

关于多ViewHolder的参考 - https://dev59.com/F18d5IYBdhLWcg3w8WJt#26245463


3

Kotlin

对于每个位于滚动视图下方的 RecyclerView,请将 isNestedScrollingEnabled 设置为 false

val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.isNestedScrollingEnabled = false

使用XML布局

<android.support.v7.widget.RecyclerView
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    android:id="@+id/friendsList"
    android:layout_width="match_parent"
    android:nestedScrollingEnabled="false"
    android:layout_height="wrap_content" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接