when studio setcolorschemecolors scrolling recyclerview recargar pulltorefresh pullrefresh onrefresh how down android android-recyclerview footer

android - studio - Cómo implementar pie de página adhesivo en recyclerview



recargar un recyclerview (6)

Tengo RecyclerView y necesito el siguiente comportamiento:

  • si hay muchos elementos (más de los que se ajustan a la pantalla) - el pie de página es el último elemento
  • Si hay pocos elementos o ningún elemento, el pie de página se encuentra en la parte inferior de la pantalla.

Por favor avise cómo puedo implementar este comportamiento.


Estoy usando un Linearlayout con pesas. Creé múltiples valores para el peso del pie de página, funciona perfectamente.

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" android:orientation="vertical" <include layout="@layout/header" /> <android.support.v7.widget.RecyclerView android:id="@+id/recycleView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.5" tools:layout_height="0dp" tools:listitem="@layout/row" /> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="@dimen/footer_weight" android:padding="@dimen/extra_padding" android:paddingEnd="@dimen/small_padding" android:paddingLeft="@dimen/small_padding" android:paddingRight="@dimen/small_padding" android:paddingStart="@dimen/small_padding" android:text="@string/contact" android:textColor="@color/grey" /> </LinearLayout>


Improvisando en Dmitriy Korobeynikov y resolviendo el problema de llamar, cambiar el conjunto de datos

public class StickyFooterItemDecoration extends RecyclerView.ItemDecoration { @Override public void getItemOffsets(Rect outRect, final View view, final RecyclerView parent, RecyclerView.State state) { int position = parent.getChildAdapterPosition(view); int adapterItemCount = parent.getAdapter().getItemCount(); if (adapterItemCount == RecyclerView.NO_POSITION || (adapterItemCount - 1) != position) { return; } outRect.top = calculateTopOffset(parent, view, adapterItemCount); } private int calculateTopOffset(RecyclerView parent, View footerView, int itemCount) { int topOffset = parent.getHeight() - parent.getPaddingTop() - parent.getPaddingBottom() - visibleChildHeightWithFooter(parent, footerView, itemCount); return topOffset < 0 ? 0 : topOffset; } private int visibleChildHeightWithFooter(RecyclerView parent, View footerView, int itemCount) { int totalHeight = 0; int onScreenItemCount = Math.min(parent.getChildCount(), itemCount); for (int i = 0; i < onScreenItemCount - 1; i++) { RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) parent.getChildAt(i) .getLayoutParams(); int height = parent.getChildAt(i).getHeight() + layoutParams.topMargin + layoutParams.bottomMargin; totalHeight += height; } int footerHeight = footerView.getHeight(); if (footerHeight == 0) { fixLayoutSize(footerView, parent); footerHeight = footerView.getHeight(); } footerHeight = footerHeight + footerView.getPaddingBottom() + footerView.getPaddingTop(); return totalHeight + footerHeight; } private void fixLayoutSize(View view, ViewGroup parent) { // Check if the view has a layout parameter and if it does not create one for it if (view.getLayoutParams() == null) { view.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } // Create a width and height spec using the parent as an example: // For width we make sure that the item matches exactly what it measures from the parent. // IE if layout says to match_parent it will be exactly parent.getWidth() int widthSpec = View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY); // For the height we are going to create a spec that says it doesn''t really care what is calculated, // even if its larger than the screen int heightSpec = View.MeasureSpec .makeMeasureSpec(parent.getHeight(), View.MeasureSpec.UNSPECIFIED); // Get the child specs using the parent spec and the padding the parent has int childWidth = ViewGroup.getChildMeasureSpec(widthSpec, parent.getPaddingLeft() + parent.getPaddingRight(), view.getLayoutParams().width); int childHeight = ViewGroup.getChildMeasureSpec(heightSpec, parent.getPaddingTop() + parent.getPaddingBottom(), view.getLayoutParams().height); // Finally we measure the sizes with the actual view which does margin and padding changes to the sizes calculated view.measure(childWidth, childHeight); // And now we setup the layout for the view to ensure it has the correct sizes. view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); } }


Puede usar RecyclerView.ItemDecoration para implementar este comportamiento.

public class StickyFooterItemDecoration extends RecyclerView.ItemDecoration { /** * Top offset to completely hide footer from the screen and therefore avoid noticeable blink during changing position of the footer. */ private static final int OFF_SCREEN_OFFSET = 5000; @Override public void getItemOffsets(Rect outRect, final View view, final RecyclerView parent, RecyclerView.State state) { int adapterItemCount = parent.getAdapter().getItemCount(); if (isFooter(parent, view, adapterItemCount)) { //For the first time, each view doesn''t contain any parameters related to its size, //hence we can''t calculate the appropriate offset. //In this case, set a big top offset and notify adapter to update footer one more time. //Also, we shouldn''t do it if footer became visible after scrolling. if (view.getHeight() == 0 && state.didStructureChange()) { hideFooterAndUpdate(outRect, view, parent); } else { outRect.set(0, calculateTopOffset(parent, view, adapterItemCount), 0, 0); } } } private void hideFooterAndUpdate(Rect outRect, final View footerView, final RecyclerView parent) { outRect.set(0, OFF_SCREEN_OFFSET, 0, 0); footerView.post(new Runnable() { @Override public void run() { parent.getAdapter().notifyDataSetChanged(); } }); } private int calculateTopOffset(RecyclerView parent, View footerView, int itemCount) { int topOffset = parent.getHeight() - visibleChildsHeightWithFooter(parent, footerView, itemCount); return topOffset < 0 ? 0 : topOffset; } private int visibleChildsHeightWithFooter(RecyclerView parent, View footerView, int itemCount) { int totalHeight = 0; //In the case of dynamic content when adding or removing are possible itemCount from the adapter is reliable, //but when the screen can fit fewer items than in adapter, getChildCount() from RecyclerView should be used. int onScreenItemCount = Math.min(parent.getChildCount(), itemCount); for (int i = 0; i < onScreenItemCount - 1; i++) { totalHeight += parent.getChildAt(i).getHeight(); } return totalHeight + footerView.getHeight(); } private boolean isFooter(RecyclerView parent, View view, int itemCount) { return parent.getChildAdapterPosition(view) == itemCount - 1; } }

Asegúrese de establecer match_parent para la altura RecyclerView.

Por favor, eche un vistazo a la aplicación de ejemplo https://github.com/JohnKuper/recyclerview-sticky-footer y cómo funciona http://sendvid.com/nbpj0806

Un gran inconveniente de esta solución es que funciona correctamente solo después de notifyDataSetChanged () en una aplicación (no en la decoración interior). Con notificaciones más específicas, no funcionará correctamente y, para respaldarlas, requiere una forma más lógica. Además, puede obtener información de la biblioteca recyclerview-stickyheaders de eowise y mejorar esta solución.


Sé que esta es una pregunta antigua, pero agregaré una respuesta para aquellos que buscarán esa decisión en el futuro. Es POSIBLE mantener el último elemento en la parte inferior de la pantalla en caso de que tenga pocos o ningún elemento y hacer que el último elemento se desplace con el recyclerview cuando tenga muchos elementos.

Cómo lograrlo . El adaptador RecyclerView debe aplicar varios tipos de vista: vistas, que deben mostrarse como un elemento de la lista; vista, que debe mostrarse como pie de página; Una vista vacía. Puede consultar cómo colocar elementos con diferentes vistas en RecyclerView aquí: https://.com/a/29362643/6329995 Busque una vista vacía entre su lista principal y la vista de pie de página. Luego, en onBindViewHolder para la vista vacía, compruebe si las vistas de la lista principal y la vista de pie de página toman todas las pantallas. En caso afirmativo, establezca la altura de la vista vacía en cero; Eso es todo. También puede actualizar esa altura dinámicamente, cuando elimine / agregue filas. Simplemente llame a NotifyItemChanged para su elemento de espacio vacío después de actualizar la lista.

También ajustaría su altura RecyclerView a match_parent o la altura exacta, NO wrap_content!

Espero que esto ayude.


Si no puede olvidarse de RecyclerView y usar ListView, vaya a ver este enlace ¿Hay un equivalente addHeaderView para RecyclerView? Tiene todo lo que necesitas. Se trata de encabezado, pero es casi lo mismo, excepto que el encabezado está al principio de tu lista y el pie de página está al final.


Todas estas soluciones no funcionan. Cuando minimiza la aplicación y la abre de nuevo, el pie de página se desplaza más abajo de la parte inferior de la pantalla y debe desplazarse para verla, incluso si solo hay 1-2 elementos. Puede agregar una vista de pie de página debajo de su vista de reciclador en xml.

<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white"> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:overScrollMode="never" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="wrap_content" /> <android.support.v4.widget.Space android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:minHeight="1dp" /> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <include layout="@layout/recyclerView_footer" /> </FrameLayout> </LinearLayout> </android.support.v4.widget.NestedScrollView>

Preste atención: usé NestedScrollView con

recyclerView.isNestedScrollingEnabled = false

y SpaceView has weight 1 and height = 0dp y todo esto dentro del linear layout y NestedScrollView has height = match_parent , ahora tengo el pie de página pegado a la parte inferior y se mueve más cuando la lista se hace más grande