Recyclerview à l'intérieur de ScrollView ne défile pas correctement

179

Pour mon application, j'utilise un RecyclerViewinside a ScrollViewoù le RecyclerViewa une hauteur basée sur son contenu en utilisant cette bibliothèque . Le défilement fonctionne mais il ne fonctionne pas correctement lorsque je fais défiler le fichier RecyclerView. Lorsque je défile sur ScrollViewlui - même, il défile en douceur.

Le code que j'utilise pour définir RecyclerView:

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

Le RecyclerViewdans le 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
la source
cette solution fonctionne pour moi: stackoverflow.com/a/32390370/7308789 merci
Houssin Boulla
1
@tahaDev ce qui ne fonctionne pas exactement dans votre cas, veuillez en dire plus à ce sujet. En outre, il semble qu'aucune solution fournie ne fonctionne dans votre cas, n'est-ce pas?
Pravin Divraniya
Utilisez androidx.constraintlayout.widget.ConstraintLayoutqui résoudra votre problème sans aucune implémentation complexe
Saswata

Réponses:

379

Essayez de faire:

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

Vous pouvez également modifier votre mise en page à l'aide de la bibliothèque de conception de support. Je suppose que votre mise en page actuelle est quelque chose comme:

<ScrollView >
   <LinearLayout >

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

   </LinearLayout >
</ScrollView >

Vous pouvez modifier cela pour:

<CoordinatorLayout >

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

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

</CoordinatorLayout >

Cependant, la route est plus longue et si vous êtes d'accord avec le gestionnaire de mise en page linéaire personnalisé, désactivez simplement le défilement imbriqué dans la vue du recycleur.

Modifier (03/04/2016)

La v 23.2version des bibliothèques de support inclut désormais une fonction d'usine de «wrapper le contenu» dans tous les LayoutManagers par défaut . Je ne l'ai pas testé, mais vous devriez probablement le préférer à la bibliothèque que vous utilisiez.

<ScrollView >
   <LinearLayout >

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

   </LinearLayout >
</ScrollView >
natario
la source
16
Pour ajouter à cette réponse: setNestedScrollingEnabled(false)n'a fonctionné que lorsque j'ai changé le ScrollViewpour un à la NestedScrollViewplace.
Richard Le Mesurier
11
Pour moi, setNestedScrollingEnabled(false)m'a redonné un défilement fluide avec mon RecyclerViewintérieur d'un ScrollView- Merci! Mais je ne comprends toujours pas pourquoi cela fonctionne ...? Que signifie vraiment définir le défilement imbriqué sur false?
Micro
33
Notez que cela android:nestedScrollingEnabled="false"ne fonctionne que pour l'API 21+ mais v.setNestedScrollingEnabled(false)est OK pour <21.
Eric B.
3
Pour référence future, si quelqu'un rencontre RecyclerViewun problème wrap_content à l'intérieur ScrollViewqui ne se produit que sur les appareils marshmallow / nougat (API 23, 24), vérifiez ma solution de contournement sur stackoverflow.com/a/38995399/132121
Hossain Khan
2
Un inconvénient de cette solution que je rencontre actuellement est que le RecyclerView ne recevra pas d'événements dans son onScrollListener. Ce dont j'ai besoin parce que je veux récupérer plus de données alors que je n'ai qu'une certaine quantité d'articles dans le recycleur
Daniel W.
82

J'avais seulement besoin d'utiliser ceci:

mMyRecyclerView.setNestedScrollingEnabled(false);

dans ma onCreateView()méthode.

Merci beaucoup!

Victor Augusto
la source
26

Vous pouvez utiliser de cette façon soit:

Ajoutez cette ligne à votre fichier xml recyclerView:

android:nestedScrollingEnabled="false"

Ou en code java:

RecyclerView.setNestedScrollingEnabled(false);

J'espère que cela a aidé.

iDeveloper
la source
10
nécessite Api 21+
Muhammad Riyaz
11

Vous pouvez essayer les deux méthodes avec XML et par programmation. Mais le problème que vous pouvez rencontrer est (en dessous de l'API 21) en le faisant avec XML ne fonctionnera pas. Il est donc préférable de le définir par programme dans votre activité / fragment.

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

Par programme:

 recycleView = (RecyclerView) findViewById(R.id.recycleView);
 recycleView.setNestedScrollingEnabled(false);
Pramod Baggolli
la source
6

L'utilisation de la vue de défilement imbriquée au lieu de la vue de défilement a résolu mon problème

<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>
Astuces Siddy
la source
5

J'ai eu des problèmes similaires (j'ai essayé de créer un RecyclerViews imbriqué quelque chose comme la conception de Google PlayStore). La meilleure façon de gérer cela est de sous-classer les RecyclerViews enfants et de remplacer les méthodes «onInterceptTouchEvent» et «onTouchEvent». De cette façon, vous obtenez un contrôle complet du comportement de ces événements et éventuellement du défilement.

mahabudhi
la source
3

Le remplacement de ScrollView par NestedScrollView a entraîné un défilement fluide vers le bas.

kapsid
la source
1

Si vous utilisez VideoView ou des widgets lourds dans vos vues enfants, gardez votre RecyclerView avec une hauteur à l' wrap_content intérieur d'un NestedScrollView avec une hauteur.Le match_parent défilement fonctionnera aussi parfaitement que vous le souhaitez.

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>

Merci Micro, c'était de votre indice!

Karthik

développeur pkarthik
la source
1

Résumé de toutes les réponses (avantages et inconvénients)

Pour une vue sur le recyclage unique

vous pouvez l'utiliser dans la mise en page Coordinator.

Avantage - il ne chargera pas des éléments entiers de recyclage Chargement si fluide.

Inconvénient - vous ne pouvez pas charger deux vues de recyclage dans la mise en page Coordinator - cela produit des problèmes de défilement

référence - https://stackoverflow.com/a/33143512/3879847

Pour une recylographie multiple avec un minimum de lignes

vous pouvez charger dans NestedScrollView

Avantage - il défilera en douceur

Inconvénient - Il charge toutes les lignes de recyclerview afin que votre activité s'ouvre avec un retard

référence - https://stackoverflow.com/a/33143512/3879847

Pour une recylographie multiple avec de grandes lignes (plus de 100)

Vous devez aller avec recyclerview.

Avantage - Faites défiler en douceur, chargez en douceur

Inconvénient - Vous devez écrire plus de code et de logique

Chargez chaque vue de recyclage dans la vue de recyclage principale à l'aide de multi-vues

ex:

MainRecyclerview

-ChildRecyclerview1 (ViewHolder1)

-ChildRecyclerview2 (ViewHolder2)

-ChildRecyclerview3 (ViewHolder3) 

-Any other layout   (ViewHolder4)

Référence pour multi-viewHolder - https://stackoverflow.com/a/26245463/3879847

Ranjith Kumar
la source
0

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

en code java:

  recycleView = (RecyclerView) findViewById(R.id.recycleView);
     recycleView.setNestedScrollingEnabled(false);
Mohsinali
la source
0

Ou vous pouvez simplement définir android:focusableInTouchMode="true"dans votre vue recycleur

Sandeep Devrari
la source
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>

Ce code fonctionne pour dans ConstraintLayout android

Hitesh sapra
la source
0

Kotlin

Défini isNestedScrollingEnabledsur falsepour chaque RecyclerView qui se trouve sous la vue de défilement

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

Utilisation de la mise en page 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
la source