with recyclerview example android android-recyclerview

android - example - ¿Cómo usar RecyclerView dentro de NestedScrollView?



scroll recyclerview (20)

¿Cómo usar RecyclerView dentro de NestedScrollView ? RecyclerView contenido de RecyclerView no es visible después de configurar el adaptador.

ACTUALIZACIÓN del código de diseño actualizado.

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/keyline_1"> </RelativeLayout> <View android:id="@+id/separator" android:layout_width="match_parent" android:layout_height="1dp" android:background="#e5e5e5" /> <android.support.v7.widget.RecyclerView android:id="@+id/conversation" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </android.support.v4.widget.NestedScrollView>


RecyclerView con NestedScrollView

<android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" />


1) Debe usar la biblioteca de soporte 23.2.0 (o) anterior

2) y la altura de RecyclerView será wrap_content .

3) recyclerView.setNestedScrollingEnabled(false)

Pero al hacer esto, el patrón de reciclador no funciona. (es decir, todas las vistas se cargarán a la vez porque wrap_content necesita la altura de RecyclerView completa, por lo que dibujará todas las View secundarias a la vez. Ninguna vista se reciclará). Intente no utilizar este patrón de utilidad a menos que sea realmente necesario. Intente usar viewType y agregue todas las demás vistas que necesitan desplazarse a RecyclerView lugar de usar RecyclerView en Scrollview . El impacto en el rendimiento será muy alto.

Para hacerlo simple, "simplemente actúa como LinearLayout con todas las vistas secundarias"


Aquí está el código que estoy usando para evitar problemas de desplazamiento:

mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list); mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); mRecyclerView.getLayoutManager().setAutoMeasureEnabled(true); mRecyclerView.setNestedScrollingEnabled(false); mRecyclerView.setHasFixedSize(false);


Hay muchas buenas respuestas. La clave es que debe establecer nestedScrollingEnabled en false . Como se mencionó anteriormente, puede hacerlo en código java:

mRecyclerView.setNestedScrollingEnabled(false);

Pero también tiene la oportunidad de establecer la misma propiedad en el código xml ( android:nestedScrollingEnabled="false" ):

<android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:nestedScrollingEnabled="false" android:layout_width="match_parent" android:layout_height="match_parent" />


Hay un código simple y de prueba que puede verificar

<android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent"/> </android.support.v4.widget.NestedScrollView>


Intente utilizar esta biblioteca: https://github.com/serso/android-linear-layout-manager .

LayoutManager de la biblioteca hace que RecyclerView envuelva su contenido. En este caso, RecyclerView será "tan grande como las vistas internas", por lo que no tendrá barras de desplazamiento y el usuario utilizará las capacidades de desplazamiento de NestedScrollView. Por lo tanto, no será ambiguo como "desplazable dentro de desplazable".


No puede usar una vista de reciclador dentro de una vista de desplazamiento anidada. No está destinado a contener más vistas desplazables, pero es porque es un elemento secundario de un diseño de desplazamiento en sí mismo que necesita la vista de desplazamiento anidada. Tuve el mismo problema, pero al final moví mi vista de texto para que fuera una vista de encabezado dentro de la vista de reciclaje, hice que la vista de reciclaje fuera un elemento directo del diseño del coordinador y eliminé la vista de desplazamiento anidada. Entonces todos mis problemas se fueron.


Para androidx se llama androidx.core.widget.NestedScrollView , y también se desplaza por igual con las propiedades isScrollContainer y measureAllChildren habilitado:

<!-- Scrolling Content --> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:isScrollContainer="true" android:measureAllChildren="true" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" android:fastScrollEnabled="true" android:scrollbarStyle="insideInset" android:scrollbars="vertical" android:splitMotionEvents="false" android:verticalScrollbarPosition="right"/> </androidx.core.widget.NestedScrollView>


Puede usar android:fillViewport="true" para hacer que NestedScrollView mida el RecyclerView . RecyclerView llenará la altura restante. así que si desea desplazarse por NestScrollView , puede configurar NestScrollView RecyclerView .


Reemplace su recyclerView con,

<android.support.v7.widget.RecyclerView android:id="@+id/conversation" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_width="match_parent" android:layout_height="wrap_content" />

aquí,

app:layout_behavior="@string/appbar_scrolling_view_behavior"

gestionará el resto de las cosas.

Una cosa más, no es necesario poner su reciclador Ver dentro de NestedScrollView


Si está utilizando RecyclerView-23.2.1 o posterior. La siguiente solución funcionará bien:

En su diseño, agregue RecyclerView así:

<android.support.v7.widget.RecyclerView android:id="@+id/review_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical" />

Y en tu archivo java:

RecyclerView mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView); LinearLayoutManager layoutManager=new LinearLayoutManager(getContext()); layoutManager.setAutoMeasureEnabled(true); mRecyclerView.setLayoutManager(layoutManager); mRecyclerView.setHasFixedSize(true); mRecyclerView.setAdapter(new YourListAdapter(getContext()));

Aquí layoutManager.setAutoMeasureEnabled(true); Hará el truco.

Consulte este tema y este blog de desarrolladores para obtener más información.


Si está utilizando RecyclerView ScrollListener dentro de NestedScrollView , addOnScrollListener oyente no funciona correctamente si se utilizan ambos.

Usa este código.

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); ...... } });

este código funciona bien RecyclerView ScrollListener dentro de NestedScrollView .

Gracias


Simplemente agregue recyclerView.setNestedScrollingEnabled(false); antes de que setAdapter funcionara para mí. No app:layout_behavior="@string/appbar_scrolling_view_behavior" ninguna parte y no configuré ningún administrador de diseño personalizado

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/white" android:text="Some Text..." android:padding="15dp" /> </LinearLayout> <LinearLayout android:orientation="vertical" android:padding="15dp" android:layout_marginTop="10dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Quick Links" android:textColor="@color/black" android:textStyle="bold" android:textAllCaps="true" android:paddingLeft="20dp" android:drawableLeft="@drawable/ic_trending_up_black_24dp" android:drawablePadding="10dp" android:layout_marginBottom="10dp" android:textSize="16sp"/> <View android:layout_width="fill_parent" android:layout_height="1dp" android:background="#efefef"/> <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </LinearLayout> </android.support.v4.widget.NestedScrollView>


Tengo Viewpager y RecyclerView dentro de NestedScrollView. Después de agregar las siguientes líneas

recyclerView.setNestedScrollingEnabled(false); recyclerView.setHasFixedSize(false);

Resolví el problema de desplazamiento lento y retraso de desplazamiento.


Tuve que implementar CoordinatorLayout con el desplazamiento de la barra de herramientas y me llevó todo el día jugar con esto. Lo tengo funcionando eliminando NestedScrollView en absoluto. Así que solo estoy usando RelativeLayout en la raíz.

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/rv_nearby" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </RelativeLayout>


Una solución para mantener la función de reciclaje de la vista de reciclaje y evitar que la vista de reciclaje cargue todos sus datos es establecer una altura fija en la vista de reciclaje. Al hacer esto, la vista del reciclador se limita solo a cargar tanto como su altura pueda mostrar al usuario, reciclando así su elemento si alguna vez se desplaza hacia abajo / arriba.


no use recyclerView dentro de NestedScrollView. ¡Puede causar problemas en cascada! Sugiero usar ItemViewTypes en RecyclerView para manejar múltiples tipos de vistas. simplemente agregue un RecyclerView con match_parent ancho y alto. luego, en su recyclerViewAdapter, anule getItemViewType y use la posición para manejar qué diseño se inflará. después de eso, puede manejar su soporte de vista utilizando el método onBindViewHolder.


ACTUALIZACIÓN 1

Desde Android Support Library 23.2.0 se agregaron métodos setAutoMeasureEnabled(true) para LayoutManagers. Hace que RecyclerView ajuste su contenido y funciona de maravilla.
http://android-developers.blogspot.ru/2016/02/android-support-library-232.html

Así que solo agrega algo como esto:

LayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setAutoMeasureEnabled(true); recyclerView.setLayoutManager(layoutManager); recyclerView.setNestedScrollingEnabled(false);


ACTUALIZACIÓN 2

Dado que 27.1.0 setAutoMeasureEnabled está en desuso, por lo que debe proporcionar una implementación personalizada de LayoutManager con el método anulado isAutoMeasureEnabled()

Pero después de muchos casos de uso de RecyclerView, recomiendo no usarlo en modo envolvente , porque esto no es para lo que está destinado. Intente refactorizar todo su diseño utilizando RecyclerView normal con varios tipos de elementos. O utilice el enfoque con LinearLayout que describí a continuación como último recurso


Respuesta anterior (no recomendada)

Puede usar RecyclerView dentro de NestedScrollView . En primer lugar, debe implementar su propio LinearLayoutManager personalizado, hace que su RecyclerView LinearLayoutManager su contenido. Por ejemplo:

public class WrappingLinearLayoutManager extends LinearLayoutManager { public WrappingLinearLayoutManager(Context context) { super(context); } private int[] mMeasuredDimension = new int[2]; @Override public boolean canScrollVertically() { return false; } @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { final int widthMode = View.MeasureSpec.getMode(widthSpec); final int heightMode = View.MeasureSpec.getMode(heightSpec); final int widthSize = View.MeasureSpec.getSize(widthSpec); final int heightSize = View.MeasureSpec.getSize(heightSpec); int width = 0; int height = 0; for (int i = 0; i < getItemCount(); i++) { if (getOrientation() == HORIZONTAL) { measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), heightSpec, mMeasuredDimension); width = width + mMeasuredDimension[0]; if (i == 0) { height = mMeasuredDimension[1]; } } else { measureScrapChild(recycler, i, widthSpec, View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), mMeasuredDimension); height = height + mMeasuredDimension[1]; if (i == 0) { width = mMeasuredDimension[0]; } } } switch (widthMode) { case View.MeasureSpec.EXACTLY: width = widthSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } switch (heightMode) { case View.MeasureSpec.EXACTLY: height = heightSize; case View.MeasureSpec.AT_MOST: case View.MeasureSpec.UNSPECIFIED: } setMeasuredDimension(width, height); } private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) { View view = recycler.getViewForPosition(position); if (view.getVisibility() == View.GONE) { measuredDimension[0] = 0; measuredDimension[1] = 0; return; } // For adding Item Decor Insets to view super.measureChildWithMargins(view, 0, 0); RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); int childWidthSpec = ViewGroup.getChildMeasureSpec( widthSpec, getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view), p.width); int childHeightSpec = ViewGroup.getChildMeasureSpec( heightSpec, getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view), p.height); view.measure(childWidthSpec, childHeightSpec); // Get decorated measurements measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin; measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin; recycler.recycleView(view); } }

Después de eso, use este LayoutManager para su RecyclerView

recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));

Pero también debe llamar a esos dos métodos:

recyclerView.setNestedScrollingEnabled(false); recyclerView.setHasFixedSize(false);

Aquí setNestedScrollingEnabled(false) deshabilita el desplazamiento para RecyclerView , por lo que no intercepta el evento de desplazamiento de NestedScrollView . Y setHasFixedSize(false) determina que los cambios en el contenido del adaptador pueden cambiar el tamaño de RecyclerView

Nota importante: esta solución es poco defectuosa en algunos casos y tiene problemas con el rendimiento, por lo que si tiene muchos elementos en su RecyclerView , recomendaría usar una implementación de vista de lista basada en LinearLayout personalizada, crear un análogo del adaptador para ella y hacer que se comporte como ListView o RecyclerView


Esto es lo que funciona para mi

<android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v7.widget.RecyclerView android:id="@+id/rv_recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </android.support.v4.widget.NestedScrollView>


Usé RecyclerView dentro de un NestedScrollView y funcionó para mí. El único problema que tuve que tener en cuenta fue que un NestedScrollView solo toma una vista secundaria. Entonces, en mi caso, utilicé el grupo de vista LienearLayout, que albergaba mi RecyclerView más otras vistas que necesitaba.

Experimento un problema al colocar mi RecyclerView dentro de NestedScrollView. Me di cuenta de que desplazar el contenido de mi RecyclerView se aflojó.

Más tarde me di cuenta de que mi RecyclerView estaba recibiendo el evento de desplazamiento y, por lo tanto, estaba en conflicto con el comportamiento de desplazamiento de NestedScrollView.

Entonces, para resolver ese problema, tuve que deshabilitar la funcionalidad de desplazamiento de mi RecyclerView con este método movieListNewRecyclerView.setNestedScrollingEnabled(false);

Puedes ver mi Instagram para ver un video corto de lo que realmente hice. Este es mi identificador de instagram ofelix03

Haga clic en esta imagen para ver lo que hice.