Recyclerview bên trong ScrollView không cuộn trơn tru


179

Đối với ứng dụng của tôi, tôi đang sử dụng một RecyclerViewbên trong ScrollViewnơi RecyclerViewcó chiều cao dựa trên nội dung của nó bằng thư viện này . Cuộn đang hoạt động nhưng nó không hoạt động trơn tru khi tôi cuộn qua RecyclerView. Khi tôi cuộn qua ScrollViewchính nó, nó đang cuộn trơn tru.

Mã tôi đang sử dụng để xác định RecyclerView:

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

Các RecyclerViewtrong ScrollView:

<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" />

giải pháp này hiệu quả với tôi: stackoverflow.com/a/32390370/7308789 cảm ơn bạn
Houssin Boulla

1
@tahaDev chính xác những gì không hoạt động trong trường hợp của bạn xin vui lòng giải thích thêm về điều đó. Ngoài ra, có vẻ như không có giải pháp được cung cấp nào hoạt động trong trường hợp của bạn, phải vậy không?
Pravin Divraniya

Sử dụng androidx.constraintlayout.widget.ConstraintLayoutsẽ giải quyết vấn đề của bạn mà không có bất kỳ triển khai phức tạp nào
Saswata

Câu trả lời:


379

Hãy thử làm:

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

Thay thế, bạn có thể sửa đổi bố cục của mình bằng thư viện thiết kế hỗ trợ. Tôi đoán bố cục hiện tại của bạn là một cái gì đó như:

<ScrollView >
   <LinearLayout >

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

   </LinearLayout >
</ScrollView >

Bạn có thể sửa đổi điều đó thành:

<CoordinatorLayout >

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

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

</CoordinatorLayout >

Tuy nhiên, đây là một con đường dài hơn để đi và nếu bạn ổn với trình quản lý bố cục tuyến tính tùy chỉnh, thì chỉ cần vô hiệu hóa cuộn lồng nhau trên chế độ xem của trình tái chế.

Chỉnh sửa (4/3/2016)

Việc v 23.2phát hành các thư viện hỗ trợ hiện bao gồm một tính năng của nhà sản xuất gói nội dung trong tất cả các LayoutManagers mặc định . Tôi đã không kiểm tra nó, nhưng có lẽ bạn nên thích nó hơn thư viện mà bạn đang sử dụng.

<ScrollView >
   <LinearLayout >

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

   </LinearLayout >
</ScrollView >

16
Để thêm vào câu trả lời này: setNestedScrollingEnabled(false)chỉ làm việc khi tôi chuyển ra ScrollViewcho một NestedScrollViewthay thế.
Richard Le Mesurier

11
Đối với tôi, setNestedScrollingEnabled(false)đã cho tôi trở lại di chuyển trơn tru với RecyclerViewbên trong của tôi ScrollView- Cảm ơn! Nhưng tôi vẫn không hiểu tại sao nó hoạt động ...? Điều gì thực sự có nghĩa là để đặt cuộn lồng nhau sai?
Micro

33
Lưu ý rằng android:nestedScrollingEnabled="false"chỉ hoạt động cho API 21+ nhưng v.setNestedScrollingEnabled(false)vẫn ổn với <21.
Eric B.

3
Để tham khảo trong tương lai, nếu ai đang trải qua RecyclerViewvấn đề wrap_content bên trong ScrollViewchỉ xảy ra trên marshmallow / kẹo hạnh phúc (API 23, 24) các thiết bị, kiểm tra workaround của tôi tại stackoverflow.com/a/38995399/132121
Hossain Khan

2
Một nhược điểm của giải pháp này hiện tại tôi đang gặp phải là RecyclerView sẽ không nhận được các sự kiện trong onScrollListener. Tôi cần bởi vì tôi muốn tìm nạp thêm dữ liệu khi tôi chỉ có một số lượng vật phẩm nhất định trong trình tái chế
Daniel W.

82

Tôi chỉ cần sử dụng cái này:

mMyRecyclerView.setNestedScrollingEnabled(false);

trong onCreateView()phương pháp của tôi .

Cảm ơn rất nhiều!


26

Bạn có thể sử dụng theo cách này:

Thêm dòng này vào tệp xml recyclerView của bạn:

android:nestedScrollingEnabled="false"

Hoặc trong mã java:

RecyclerView.setNestedScrollingEnabled(false);

Hy vọng điều này sẽ giúp.


10
yêu cầu Api 21+
Muhammad Riyaz

11

Bạn có thể thử với cả hai cách với XML và lập trình. Nhưng vấn đề bạn có thể gặp phải là (dưới API 21) bằng cách thực hiện với XML sẽ không hoạt động. Vì vậy, tốt hơn là đặt nó theo chương trình trong Activity / Fragment của bạn.

Mã 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" /> 

Lập trình:

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

6

Sử dụng Nested Scroll View thay vì Scroll View đã giải quyết vấn đề của tôi

<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

Tôi đã gặp vấn đề tương tự (tôi đã cố gắng tạo RecyclerViews lồng nhau giống như thiết kế Google PlayStore). Cách tốt nhất để giải quyết vấn đề này là phân lớp các RecyclerViews con và ghi đè các phương thức 'onInterceptTouchEvent' và 'onTouchEvent'. Bằng cách này bạn có thể kiểm soát hoàn toàn cách các sự kiện đó hoạt động và cuối cùng là cuộn.


3

Thay thế ScrollView bằng NestedScrollView dẫn đến việc cuộn trơn tru xuống phía dưới.


1

Nếu bạn đang sử dụng VideoView hoặc các vật nặng có trọng lượng trong các lần xem con, hãy giữ RecyclerView có chiều cao wrap_content bên trong NestedScrollView với chiều cao match_parent Sau đó, cuộn sẽ hoạt động trơn tru như bạn muốn.

FYI,

<android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:nestedScrollingEnabled="false"
            android:layout_height="wrap_content"
            android:clipToPadding="false" />

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

Cảm ơn Micro đây là từ gợi ý của bạn!

karthik


1

Tóm tắt tất cả các câu trả lời (Ưu điểm & nhược điểm)

Đối với tái chế đơn

bạn có thể sử dụng nó trong bố trí Điều phối viên.

Ưu điểm - nó sẽ không tải toàn bộ các mục tái chế. Vì vậy, tải trơn tru.

Nhược điểm - bạn không thể tải hai recyclerview trong bố trí Điều phối viên - nó tạo ra các vấn đề cuộn

tham khảo - https://stackoverflow.com/a/33143512/3879847

Đối với nhiều recylerview với các hàng tối thiểu

bạn có thể tải bên trong NestedScrollView

Ưu điểm - nó sẽ cuộn trơn tru

Nhược điểm - Nó tải tất cả các hàng của recyclerview để hoạt động của bạn mở với độ trễ

tham khảo - https://stackoverflow.com/a/33143512/3879847

Đối với nhiều recylerview có hàng lớn (hơn 100)

Bạn phải đi với recyclerview.

Ưu điểm - Di chuyển mượt mà, tải mượt mà

Bất lợi - Bạn cần viết thêm mã và logic

Tải mỗi recylerview bên trong recyclerview chính với sự trợ giúp của nhiều người xem

Ví dụ:

MainRecyclerview

-ChildRecyclerview1 (ViewHolder1)

-ChildRecyclerview2 (ViewHolder2)

-ChildRecyclerview3 (ViewHolder3) 

-Any other layout   (ViewHolder4)

Tham khảo cho nhiều người xemHolder - https://stackoverflow.com/a/26245463/3879847


0

Mã XML:

<android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v7.widget.RecyclerView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:clipToPadding="false" />

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

trong mã java:

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

0

Hoặc bạn chỉ có thể đặt android:focusableInTouchMode="true"trong chế độ xem tái chế của mình


0
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent">

            <android.support.constraint.ConstraintLayout
                android:id="@+id/constraintlayout_main"
                android:layout_width="match_parent"
                android:layout_height="@dimen/layout_width_height_fortyfive"
                android:layout_marginLeft="@dimen/padding_margin_sixteen"
                android:layout_marginRight="@dimen/padding_margin_sixteen"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent">

                <TextView
                    android:id="@+id/textview_settings"
                    style="@style/textviewHeaderMain"
                    android:gravity="start"
                    android:text="@string/app_name"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintRight_toRightOf="parent" />

            </android.support.constraint.ConstraintLayout>

            <android.support.constraint.ConstraintLayout
                android:id="@+id/constraintlayout_recyclerview"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/padding_margin_zero"
                android:layout_marginTop="@dimen/padding_margin_zero"
                android:layout_marginEnd="@dimen/padding_margin_zero"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/constraintlayout_main">

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerview_list"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:nestedScrollingEnabled="false"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintRight_toRightOf="parent" />

            </android.support.constraint.ConstraintLayout>

        </android.support.constraint.ConstraintLayout>

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

</android.support.constraint.ConstraintLayout>

Mã này đang hoạt động trong Android ConstraintLayout


0

Kotlin

Đặt isNestedScrollingEnabledthành falsecho mọi RecyclerView dưới chế độ xem cuộn

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

Sử dụng Bố cục 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" />
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.