Cómo poner RecyclerView dentro de NestedScrollView?

Con la creación de NestedScrollView puede poner vista de desplazamiento dentro de otra vista de desplazamiento, siempre y cuando implementen NestedScrollingChild y NestedScrollingParent correctamente.

(Esto no es patrón de diseño malo "Ian Lake (de Google) en realidad recomienda poner un RecyclerView dentro de una nestedscrollview aquí: plus.google.com/u/0/+AndroidDevelopers/posts/9kZ3SsXdT2T")

Quiero poner RecyclerView dentro de NestedScrollView y, afortunadamente, RecyclerView implementa NestedScrollingChild para que pueda ponerlo dentro de NestedScrollView .

 public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild 

He leído estos mensajes:

¿Cómo usar RecyclerView dentro de NestedScrollView?

NestedScrolling con NestedScrollView, RecyclerView (Horizontal), dentro de un CoordinatorLayout

Pero el problema con la mayoría de la solución votada es, que llama a todos los elementos de RecyclerView por ejemplo, si se trata de un interminable RecyclerView y cuando el usuario llega al final de la lista que desea hacer una solicitud de red, con esa solución el RecyclerView llamadas Servidor repetidamente porque alcanza automáticamente el último elemento de RecyclerView .

De todos modos, cómo establecer el parámetro para que pueda poner RecyclerView dentro de NestedScrollView (en realidad, quiero poner un grupo de vista como framelayout o relativelayout como un único childe de nestedscrollview y luego quiero poner recyclerview dentro de framelayout o relativelayout)

Cuando pongo RecyclerView dentro de NestedScrollView no hay nada que mostrar.


Con el fin de crear un proyecto de muestra que puede utilizar cheesesquare y cambiar la CheeseDetailActivity para tener un RecyclerView.


Aunque la respuesta de BNK no es correcta, pero BNK ha intentado mucho. Así que le doy la recompensa. Todavía buscando una buena solución ….

La siguiente es mi nueva respuesta actualizada:

 <android.support.v4.widget.NestedScrollView android:id="@+id/scrollview" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:id="@+id/cardview1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/card_margin"> <LinearLayout style="@style/Widget.CardContent" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Info CardView1" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:id="@+id/cardview2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/cardview1" android:layout_margin="@dimen/card_margin"> <LinearLayout style="@style/Widget.CardContent" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Info CardView2" android:textAppearance="@style/TextAppearance.AppCompat.Title" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/cheese_ipsum" /> </LinearLayout> </android.support.v7.widget.CardView> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/cardview2" android:clipToPadding="false" android:paddingTop="0dp"/> </RelativeLayout> </android.support.v4.widget.NestedScrollView> 

En Actividad:

  RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(true); // true: with header RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); final MyLinearLayoutManager layoutManager = new MyLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false, getScreenHeight(this)); // final CustomLinearLayoutManager layoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(recyclerViewAdapter); // recyclerView.setNestedScrollingEnabled(false); // Disables scrolling for RecyclerView, however, CustomLinearLayoutManager used instead of MyLinearLayoutManager 

También he actualizado el proyecto de muestra de My GitHub

Captura de pantalla:

Introduzca aquí la descripción de la imagen


Aquí hay una solución para llamar al servidor sólo cuando realmente necesita cargar más datos. De esta manera puede poner su interminable RecyclerView y muchas otras vistas dentro de NestedScrollView. Para mí funciona bien.

1. Cree la clase EndlessParentScrollListener para manejar los eventos de desplazamiento desde NestedSrollView.

 public abstract class EndlessParentScrollListener implements NestedScrollView.OnScrollChangeListener { // The current offset index of data you have loaded private int currentPage = 0; // The total number of items in the dataset after the last load private int previousTotalItemCount = 0; // True if we are still waiting for the last set of data to load. private boolean loading = true; // Sets the starting page index private int startingPageIndex = 0; // The minimum amount of pixels to have below your current scroll position // before loading more. private int visibleThresholdDistance = 300; RecyclerView.LayoutManager mLayoutManager; public EndlessParentScrollListener(RecyclerView.LayoutManager layoutManager) { this.mLayoutManager = layoutManager; } @Override public void onScrollChange(NestedScrollView scrollView, int x, int y, int oldx, int oldy) { // We take the last son in the scrollview View view = scrollView.getChildAt(scrollView.getChildCount() - 1); int distanceToEnd = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY())); int totalItemCount = mLayoutManager.getItemCount(); // If the total item count is zero and the previous isn't, assume the // list is invalidated and should be reset back to initial state if (totalItemCount < previousTotalItemCount) { this.currentPage = this.startingPageIndex; this.previousTotalItemCount = totalItemCount; if (totalItemCount == 0) { this.loading = true; } } // If it's still loading, we check to see if the dataset count has // changed, if so we conclude it has finished loading and update the current page // number and total item count. if (loading && (totalItemCount > previousTotalItemCount)) { loading = false; previousTotalItemCount = totalItemCount; } // If it isn't currently loading, we check to see if we have breached // the visibleThreshold and need to reload more data. // If we do need to reload some more data, we execute onLoadMore to fetch the data. // threshold should reflect how many total columns there are too if (!loading && distanceToEnd <= visibleThresholdDistance) { currentPage++; onLoadMore(currentPage, totalItemCount); loading = true; } } // Defines the process for actually loading more data based on page public abstract void onLoadMore(int page, int totalItemsCount); } 

2. Establecer audiencia

 private void initRecycler() { //TODO init recycler adapter here recycler.setNestedScrollingEnabled(false); LinearLayoutManager _layoutManager = new LinearLayoutManager(this); recycler.setLayoutManager(_layoutManager); NestedScrollView scrollView = (NestedScrollView) findViewById(R.id.scrollView); scrollView.setOnScrollChangeListener(new EndlessParentScrollListener(_layoutManager) { @Override public void onLoadMore(int page, int totalItemsCount) { if (loadedItemCount < serverItemsCount) customLoadMoreDataFromApi(); } }); customLoadMoreDataFromApi(); } 

Corto xml si alguien lo encuentra útil:

 <android.support.design.widget.CoordinatorLayout 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:background="@android:color/background_light" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout> ... </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:scrollbars="vertical" android:scrollbarAlwaysDrawVerticalTrack="true" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:scrollbarAlwaysDrawVerticalTrack="false" android:scrollbars="vertical"> <!-- some views goes here--> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerFeed" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <!-- and possibly here--> </LinearLayout> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout> 

Así que poner RecyclerView dentro de NestedScrollView directamente desafortunadamente no mostrará nada. Sin embargo, hay una manera de poner el recyclerview dentro de la NestedScrollView indirectamente – sólo use un frameLayout como el tercero para mantener su recyclerview.

Esta es la framelayout que contiene la reciclerview anidada en su clase de actividad :

  <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".ExampleFragment" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" > </android.support.v4.widget.NestedScrollView> </FrameLayout> 

Ponga su fragmento en el framelayout (el código se encuentra dentro de la clase de actividad ):

  ExampleFragment exampleFragment = new ExampleFragment(); FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.add(R.id.container, exampleFragment); ft.commit(); 

En su ejemplo , usted puede entonces poner su recyclerview.

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/post_container" android:background="#E0E0E0"> <android.support.v7.widget.RecyclerView android:id="@+id/my_recycler_view" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </RelativeLayout> 

Este es el código del fragmento :

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); llLayout = (RelativeLayout) inflater.inflate(R.layout.example_fragment_layout, container, false); mRecyclerView = (RecyclerView) llLayout.findViewById(R.id.my_recycler_view); 

El siguiente es el diseño XML CheeseSquare que debe tener:

 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="@dimen/detail_backdrop_height" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:fitsSystemWindows="true"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp"> <ImageView android:id="@+id/backdrop" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:fitsSystemWindows="true" app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".ExampleFragment" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" > </android.support.v4.widget.NestedScrollView> </FrameLayout> <android.support.design.widget.FloatingActionButton android:layout_height="wrap_content" android:layout_width="wrap_content" app:layout_anchor="@id/appbar" app:layout_anchorGravity="bottom|right|end" android:src="@drawable/ic_discuss" android:layout_margin="@dimen/fab_margin" android:clickable="true"/> </android.support.design.widget.CoordinatorLayout> 
  • El rollo no funciona correctamente para RecyclerView dentro de CoordinatorLayout
  • Seleccionar todas las casillas de verificación en RecyclerView
  • Espresso Nested Recycler Vistas Prueba de interfaz de usuario
  • Al hacer clic en ActionButton flotante en la esquina derecha, se hace clic en el elemento RecyclerView
  • ¿Cómo ajustar correctamente el valor de elevación a recyclerview?
  • RecyclerView se bloquea al desplazarse
  • RecyclerView onclick se activa antes de que la animación del clic se complete
  • Recyclerview con múltiples temporizadores de cuenta regresiva causa parpadeo
  • Eliminación del indicador de foco de RecycleView en Android
  • Arrastrar y soltar entre dos RecyclerView
  • Cómo ampliar el espacio entre RecyclerView Item mientras se desplaza
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.