Recyclerview wewnątrz ScrollView nie przewija się płynnie

179

W mojej aplikacji korzystam z RecyclerViewwnętrza, w ScrollViewktórym RecyclerViewwysokość ma wysokość w oparciu o zawartość przy użyciu tej biblioteki . Przewijanie działa, ale nie działa płynnie, gdy przewijam RecyclerView. Kiedy przewijam ScrollViewsam, przewija się płynnie.

Kod, którego używam do zdefiniowania RecyclerView:

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

RecyclerViewW 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" />
Bart Bergmans
źródło
to rozwiązanie działa dla mnie: stackoverflow.com/a/32390370/7308789 dziękuję
Houssin Boulla
1
@tahaDev, co dokładnie nie działa w twoim przypadku, opisz więcej na ten temat. Wygląda na to, że żadne dostarczone rozwiązania nie działały w twoim przypadku, prawda?
Pravin Divraniya
Skorzystaj androidx.constraintlayout.widget.ConstraintLayoutz rozwiązania, które rozwiąże Twój problem bez żadnych skomplikowanych implementacji
Saswata

Odpowiedzi:

379

Spróbuj zrobić:

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

Alternatywnie możesz zmodyfikować układ za pomocą biblioteki projektu wsparcia. Myślę, że twój obecny układ jest podobny do:

<ScrollView >
   <LinearLayout >

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

   </LinearLayout >
</ScrollView >

Możesz to zmienić, aby:

<CoordinatorLayout >

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

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

</CoordinatorLayout >

Jest to jednak długa droga, a jeśli nie masz nic przeciwko niestandardowemu menedżerowi układu liniowego, wyłącz po prostu przewijanie zagnieżdżone w widoku recyklera.

Edytuj (4/3/2016)

v 23.2Wydanie bibliotek pomocniczych zawiera teraz fabryczne „content wrap” funkcję we wszystkich domyślny LayoutManagers. Nie przetestowałem tego, ale prawdopodobnie powinieneś preferować bibliotekę, której używasz.

<ScrollView >
   <LinearLayout >

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

   </LinearLayout >
</ScrollView >
natario
źródło
16
Aby dodać do tej odpowiedzi: setNestedScrollingEnabled(false)tylko pracował, kiedy włącza się z ScrollViewdotyczący NestedScrollViewzamiast.
Richard Le Mesurier,
11
Dla mnie setNestedScrollingEnabled(false)przywróciłem płynne przewijanie z moim RecyclerViewwnętrzem ScrollView- Dzięki! Ale nadal nie rozumiem, dlaczego to działa ...? Co tak naprawdę oznacza ustawienie false przewijania zagnieżdżonego?
Micro
33
Pamiętaj, że android:nestedScrollingEnabled="false"działa tylko dla API 21+, ale v.setNestedScrollingEnabled(false)jest OK dla <21.
Eric B.,
3
Na RecyclerViewwypadek , gdyby ktoś miał problem z opakowaniem w środku, ScrollViewktóry zdarza się tylko na urządzeniach marshmallow / nougat (API 23, 24), sprawdź moje obejście na stackoverflow.com/a/38995399/132121
Hossain Khan
2
Minusem tego rozwiązania, którego obecnie doświadczam, jest to, że RecyclerView nie będzie odbierał zdarzeń w swoim obiekcie onScrollListener. Które potrzebuję, ponieważ chcę pobrać więcej danych, gdy mam tylko pewną ilość przedmiotów w recyklerze
Daniel W.
82

Potrzebowałem tylko tego:

mMyRecyclerView.setNestedScrollingEnabled(false);

w mojej onCreateView()metodzie.

Wielkie dzięki!

Victor Augusto
źródło
26

Możesz użyć tej metody:

Dodaj tę linię do pliku xml recyclinglerView:

android:nestedScrollingEnabled="false"

Lub w kodzie Java:

RecyclerView.setNestedScrollingEnabled(false);

Mam nadzieję, że to pomogło.

iDeveloper
źródło
10
wymaga Api 21+
Muhammad Riyaz
11

Możesz wypróbować oba sposoby z XML i programowo. Ale problem, z którym możesz się spotkać to (poniżej API 21), gdy robi się to z XML-em, nie będzie działać. Lepiej więc ustawić to programowo w swojej aktywności / fragmencie.

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

Programowo:

 recycleView = (RecyclerView) findViewById(R.id.recycleView);
 recycleView.setNestedScrollingEnabled(false);
Pramod Baggolli
źródło
6

Używanie zagnieżdżonego widoku przewijania zamiast widoku przewijania rozwiązało mój problem

<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>
Siddy Hacks
źródło
5

Miałem podobne problemy (próbowałem utworzyć zagnieżdżony RecyclerViews podobny do projektu Google PlayStore). Najlepszym sposobem na poradzenie sobie z tym jest podklasowanie podrzędnych RecyclerViews i przesłanianie metod „onInterceptTouchEvent” i „onTouchEvent”. W ten sposób zyskujesz pełną kontrolę nad tym, jak zachowują się te zdarzenia, a następnie przewijaniem.

Mahabudhi
źródło
3

Zastąpienie ScrollView NestedScrollView spowodowało płynne przewijanie w dół.

kapsid
źródło
1

Jeśli korzystasz z VideoView lub widgetów o dużej gramaturze w swoich widokach dla dzieci, zachowaj RecyclerView z wysokością wrap_content w NestedScrollView z wysokością, a match_parent następnie przewijanie będzie działało tak płynnie, jak tylko chcesz.

Do Twojej wiadomości

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

Dzięki Micro to było z twojej wskazówki!

karthik

programista pkarthik
źródło
1

Podsumowanie wszystkich odpowiedzi (zalety i wady)

Dla pojedynczego podglądu recyklera

możesz go użyć w układzie koordynatora.

Zaleta - nie spowoduje załadowania całych przedmiotów do recyklingu. Tak płynne ładowanie.

Wada - nie można załadować dwóch widoków recyklera w układzie koordynatora - powoduje to problemy z przewijaniem

odniesienie - https://stackoverflow.com/a/33143512/3879847

Dla wielu recylerview z minimalnymi rzędami

możesz załadować do NestedScrollView

Zaleta - przewinie się płynnie

Wada - ładuje wszystkie rzędy widoku recyklera, dzięki czemu Twoja aktywność otwiera się z opóźnieniem

odniesienie - https://stackoverflow.com/a/33143512/3879847

Dla wielu recylerview z dużymi rzędami (ponad 100)

Musisz przejść z recyklingiem.

Zaleta - Przewijaj płynnie, ładuj płynnie

Wada - Musisz napisać więcej kodu i logiki

Załaduj każdy recylerview do głównego widoku recyklera za pomocą wielu przeglądarek

dawny:

MainRecyclerview

-ChildRecyclerview1 (ViewHolder1)

-ChildRecyclerview2 (ViewHolder2)

-ChildRecyclerview3 (ViewHolder3) 

-Any other layout   (ViewHolder4)

Odniesienie do multi-viewHolder - https://stackoverflow.com/a/26245463/3879847

Ranjith Kumar
źródło
0

Kod 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>

w kodzie java:

  recycleView = (RecyclerView) findViewById(R.id.recycleView);
     recycleView.setNestedScrollingEnabled(false);
Mohsinali
źródło
0

Lub możesz po prostu ustawić android:focusableInTouchMode="true"w widoku recyklera

Sandeep Devrari
źródło
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>

Ten kod działa w systemie Android ConstraintLayout

Hitesh sapra
źródło
0

Kotlin

Ustaw isNestedScrollingEnabledsię falseza każdym RecyclerView że jest pod widoku przewijania

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

Korzystanie z układu 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" />
anand tripathi
źródło