Recyclerview dentro de ScrollView no se desplaza suavemente


179

Para mi aplicación, estoy usando un RecyclerViewdentro de ScrollViewdonde RecyclerViewtiene una altura basada en su contenido usando esta biblioteca . El desplazamiento funciona pero no funciona correctamente cuando me desplazo sobre el RecyclerView. Cuando me desplazo sobre el ScrollViewmismo, se desplaza suavemente.

El código que estoy usando para definir el RecyclerView:

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

El RecyclerViewen el 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" />

esta solución funciona para mí: stackoverflow.com/a/32390370/7308789 gracias
Houssin Boulla

1
@tahaDev qué no funciona exactamente en su caso, por favor explique más sobre eso. Además, parece que no hay soluciones proporcionadas en su caso, ¿es así?
Pravin Divraniya

Uso androidx.constraintlayout.widget.ConstraintLayoutque resolverá su problema sin implementaciones complejas
Saswata

Respuestas:


379

Trata de hacerlo:

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

Como alternativa, puede modificar su diseño utilizando la biblioteca de diseño de soporte. Supongo que su diseño actual es algo así como:

<ScrollView >
   <LinearLayout >

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

   </LinearLayout >
</ScrollView >

Puede modificar eso para:

<CoordinatorLayout >

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

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

</CoordinatorLayout >

Sin embargo, este es un camino más largo que tomar, y si está de acuerdo con el administrador de diseño lineal personalizado, simplemente deshabilite el desplazamiento anidado en la vista del reciclador.

Editar (4/3/2016)

El v 23.2lanzamiento de las bibliotecas de soporte ahora incluye una característica de fábrica de "contenido envolvente" en todos los LayoutManagers predeterminados . No lo probé, pero probablemente deberías preferirlo a esa biblioteca que estabas usando.

<ScrollView >
   <LinearLayout >

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

   </LinearLayout >
</ScrollView >

16
Para agregar a esta respuesta: setNestedScrollingEnabled(false)solo funcionó cuando cambié el ScrollViewpor un NestedScrollViewlugar.
Richard Le Mesurier

11
Para mí, setNestedScrollingEnabled(false)me devolvió el desplazamiento suave con el RecyclerViewinterior de un ScrollView- ¡Gracias! Pero todavía no entiendo por qué eso funciona ... ¿Qué significa realmente establecer un desplazamiento anidado falso?
Micro

33
Tenga en cuenta que android:nestedScrollingEnabled="false"solo funciona para API 21+ pero v.setNestedScrollingEnabled(false)está bien para <21.
Eric B.

3
Para referencia futura, si alguien está experimentando RecyclerViewun problema de wrap_content dentro de ScrollVieweso que solo ocurre en dispositivos de malvavisco / turrón (API 23, 24), revise mi solución en stackoverflow.com/a/38995399/132121
Hossain Khan

2
Una desventaja de esta solución que estoy experimentando en este momento es que RecyclerView no recibirá eventos en su OnScrollListener. Lo que necesito porque quiero obtener más datos cuando solo tengo una cierta cantidad de elementos en el reciclador
Daniel W.

82

Solo necesitaba usar esto:

mMyRecyclerView.setNestedScrollingEnabled(false);

en mi onCreateView()metodo

¡Muchas gracias!


26

Puede usar de esta manera:

Agregue esta línea a su archivo xml de recyclerView:

android:nestedScrollingEnabled="false"

O en código java:

RecyclerView.setNestedScrollingEnabled(false);

Espero que esto haya ayudado.


10
requiere Api 21+
Muhammad Riyaz

11

Puede probar tanto con XML como mediante programación. Pero el problema que puede enfrentar es (debajo de API 21) al hacerlo con XML no funcionará. Por lo tanto, es mejor configurarlo mediante programación en su Actividad / Fragmento.

Código 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" /> 

Programáticamente:

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

6

El uso de la Vista de desplazamiento anidada en lugar de la Vista de desplazamiento resolvió mi problema

<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

Tuve problemas similares (intenté crear un RecyclerViews anidado similar al diseño de Google PlayStore). La mejor manera de lidiar con esto es subclasificar las RecyclerViews secundarias y anular los métodos 'onInterceptTouchEvent' y 'onTouchEvent'. De esta manera, obtienes el control completo de cómo se comportan esos eventos y, finalmente, el desplazamiento.


3

Reemplazar ScrollView con NestedScrollView resultó en un desplazamiento suave hacia abajo.


1

Si está utilizando VideoView o widgets pesados ​​en sus vistas de niño, mantenga su RecyclerView con altura wrap_content dentro de un NestedScrollView con altura. match_parent Luego, el desplazamiento funcionará sin problemas tan perfectamente como lo desee.

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>

¡Gracias Micro, esto fue de tu indirecta!

karthik


1

Resumen de todas las respuestas (ventajas y desventajas)

Para una sola vista de reciclado

puedes usarlo dentro del diseño del Coordinador.

Ventaja : no cargará elementos completos de la vista del reciclador. Tan suave carga.

Desventaja : no puede cargar dos vistas de reciclador dentro del diseño del Coordinador: produce problemas de desplazamiento

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

Para múltiples vistas de reciclador con filas mínimas

puedes cargar dentro de NestedScrollView

Ventaja : se desplazará suavemente

Desventaja : carga todas las filas de la vista del reciclador para que su actividad se abra con retraso

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

Para múltiples vistas de reciclador con grandes filas (más de 100)

Debes ir con la vista de reciclaje.

Ventaja : desplácese suavemente, cargue suavemente

Desventaja : necesita escribir más código y lógica

Cargue cada vista de reciclador dentro de la vista de reciclador principal con la ayuda de múltiples usuarios

ex:

MainRecyclerview

-ChildRecyclerview1 (ViewHolder1)

-ChildRecyclerview2 (ViewHolder2)

-ChildRecyclerview3 (ViewHolder3) 

-Any other layout   (ViewHolder4)

Referencia para multi-viewHolder - https://stackoverflow.com/a/26245463/3879847


0

Código 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 código java:

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

0

O simplemente puede configurar android:focusableInTouchMode="true"en su vista de reciclador


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>

Este código está funcionando en Android ConstraintLayout


0

Kotlin

Establecer isNestedScrollingEnableda falsepor cada RecyclerView que está bajo el punto de vista de desplazamiento

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

Usar diseño 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" />
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.