android header footer android-5.0-lollipop android-recyclerview

android - RecyclerView encabezado y pie de página



header footer (11)

Esto es muy fácil con ItemDecorations y sin modificar ningún otro código:

recyclerView.addItemDecoration(new HeaderDecoration(this, recyclerView, R.layout.test_header));

Reserve un espacio para dibujar, infle el diseño que desea dibujar y dibuje en el espacio reservado.

El código para la decoración:

public class HeaderDecoration extends RecyclerView.ItemDecoration { private View mLayout; public HeaderDecoration(final Context context, RecyclerView parent, @LayoutRes int resId) { // inflate and measure the layout mLayout = LayoutInflater.from(context).inflate(resId, parent, false); mLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); // layout basically just gets drawn on the reserved space on top of the first view mLayout.layout(parent.getLeft(), 0, parent.getRight(), mLayout.getMeasuredHeight()); for (int i = 0; i < parent.getChildCount(); i++) { View view = parent.getChildAt(i); if (parent.getChildAdapterPosition(view) == 0) { c.save(); final int height = mLayout.getMeasuredHeight(); final int top = view.getTop() - height; c.translate(0, top); mLayout.draw(c); c.restore(); break; } } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (parent.getChildAdapterPosition(view) == 0) { outRect.set(0, mLayout.getMeasuredHeight(), 0, 0); } else { outRect.setEmpty(); } } }

Tal vez esta pregunta ya se ha hecho antes, pero parece que no pude encontrar una respuesta o solución precisa. Comencé a usar RecyclerView, y lo implementé usando LinearLayoutManager. Ahora quiero agregar elementos de encabezado y pie de página personalizados, que difieren del resto de los elementos en mi RecyclerView. El encabezado y el pie de página no deben ser adhesivos, quiero que se desplacen con el resto de los elementos. ¿Alguien puede señalar algún ejemplo de cómo hacer esto o simplemente compartir ideas? Te lo agradeceré mucho. Gracias


Haga clic here Hice una extensión de RecyclerView.Adapter. Fácil de agregar encabezado y pie de página.

class HFAdapter extends HFRecyclerViewAdapter<String, HFAdapter.DataViewHolder>{ public HFAdapter(Context context) { super(context); } @Override public DataViewHolder onCreateDataItemViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.data_item, parent, false); return new DataViewHolder(v); } @Override public void onBindDataItemViewHolder(DataViewHolder holder, int position) { holder.itemTv.setText(getData().get(position)); } class DataViewHolder extends RecyclerView.ViewHolder{ TextView itemTv; public DataViewHolder(View itemView) { super(itemView); itemTv = (TextView)itemView.findViewById(R.id.itemTv); } } } //add header View headerView = LayoutInflater.from(this).inflate(R.layout.header, recyclerView, false); hfAdapter.setHeaderView(headerView); //add footer View footerView = LayoutInflater.from(this).inflate(R.layout.footer, recyclerView, false); hfAdapter.setFooterView(footerView); //remove hfAdapter.removeHeader(); hfAdapter.removeFooter();


Otra forma sería envolver el encabezado y el reyclerview en un coordinadorlayout :

<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.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:elevation="0dp"> <View android:id="@+id/header" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_scrollFlags="scroll" /> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" />


Puede ser GroupAdapter es lo que quieres.

Un RecyclerView.Adapter especializado que presenta datos de una secuencia de RecyclerView.Adapter. La secuencia es estática, pero cada adaptador se puede presentar en cero o más vistas de elementos. El adaptador secundario puede usar ViewType de forma segura. Además, podemos agregarHeaderView o addFooterView como ListView.


Puede usar esta biblioteca GitHub] para agregar un encabezado o pie de página a su RecyclerView de la manera más simple posible.

HFRecyclerView agregar la biblioteca HFRecyclerView en su proyecto o también puede obtenerla de Gradle:

compile ''com.mikhaellopez:hfrecyclerview:1.0.0''

Esta biblioteca se basa en un trabajo en @hister

Este es un resultado en la imagen:


Puede usar la biblioteca SectionedRecyclerViewAdapter , tiene el concepto de "Secciones", donde cada sección tiene un encabezado, pie de página y contenido (lista de elementos). En su caso, es posible que solo necesite una sección, pero puede tener muchas:

1) Crear una clase de sección personalizada:

class MySection extends StatelessSection { List<String> myList = Arrays.asList(new String[] {"Item1", "Item2", "Item3" }); public MySection() { // call constructor with layout resources for this Section header, footer and items super(R.layout.section_header, R.layout.section_footer, R.layout.section_item); } @Override public int getContentItemsTotal() { return myList.size(); // number of items of this section } @Override public RecyclerView.ViewHolder getItemViewHolder(View view) { // return a custom instance of ViewHolder for the items of this section return new MyItemViewHolder(view); } @Override public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) { MyItemViewHolder itemHolder = (MyItemViewHolder) holder; // bind your view here itemHolder.tvItem.setText(myList.get(position)); } }

2) Cree un ViewHolder personalizado para los elementos:

class MyItemViewHolder extends RecyclerView.ViewHolder { private final TextView tvItem; public MyItemViewHolder(View itemView) { super(itemView); tvItem = (TextView) itemView.findViewById(R.id.tvItem); } }

3) Configure su ReclyclerView con el SectionedRecyclerViewAdapter

// Create an instance of SectionedRecyclerViewAdapter SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter(); MySection mySection = new MySection(); // Add your Sections sectionAdapter.addSection(mySection); // Set up your RecyclerView with the SectionedRecyclerViewAdapter RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerView.setAdapter(sectionAdapter);


Si todo lo que necesita es un encabezado y pie de página en blanco, aquí hay una manera muy simple de lograr esto (escrito en Kotlin):

class HeaderFooterDecoration(private val headerHeight: Int, private val footerHeight: Int) : RecyclerView.ItemDecoration() { override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { val adapter = parent.adapter ?: return when (parent.getChildAdapterPosition(view)) { 0 -> outRect.top = headerHeight adapter.itemCount - 1 -> outRect.bottom = footerHeight else -> outRect.set(0, 0, 0, 0) } } }

Llámalo de esta manera:

recyclerView.addItemDecoration(HeaderFooterDecoration(headerHeightPx, footerHeightPx))


Sugeriría no personalizar rv adapater.

Manténgalo como está ... en el diseño de su elemento RV simplemente agregue el pie de página con el diseño y configure la visibilidad desaparecida.

Luego, cuando llegue al último elemento del adaptador ... hágalo visible.

y cuando intente esto, asegúrese de agregar esto a su adaptador de rv.

@Override public void onBindViewHolder(final PersonViewHolder personViewHolder, int i) { if(i==List.size()) // Last item in recycle view personViewHolder.tv_footer.setVisibility(VISIBLE);// Make footer visible now } @Override public int getItemViewType(int position) { return position; }

Haga lo mismo para el encabezado. Aquí i == 0 // primer elemento de la lista

La solución más fácil para mí.


aquí alguna decoración del artículo del encabezado para la vista del reciclador

con alguna modificación puede cambiar al pie de página

public class HeaderItemDecoration extends RecyclerView.ItemDecoration { private View customView; public HeaderItemDecoration(View view) { this.customView = view; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); customView.layout(parent.getLeft(), 0, parent.getRight(), customView.getMeasuredHeight()); for (int i = 0; i < parent.getChildCount(); i++) { View view = parent.getChildAt(i); if (parent.getChildAdapterPosition(view) == 0) { c.save(); final int height = customView.getMeasuredHeight(); final int top = view.getTop() - height; c.translate(0, top); customView.draw(c); c.restore(); break; } } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { if (parent.getChildAdapterPosition(view) == 0) { customView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(parent.getMeasuredHeight(), View.MeasureSpec.AT_MOST)); outRect.set(0, customView.getMeasuredHeight(), 0, 0); } else { outRect.setEmpty(); } } }


en su adaptador agregue esta clase:

private class VIEW_TYPES { public static final int Header = 1; public static final int Normal = 2; public static final int Footer = 3; }

luego anule el siguiente método como este:

@Override public int getItemViewType(int position) { if(items.get(position).isHeader) return VIEW_TYPES.Header; else if(items.get(position).isFooter) return VIEW_TYPES.Footer; else return VIEW_TYPES.Normal; }

Ahora, en el método onCreateViewHolder, infle su diseño en función del tipo de vista ::

@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View rowView; switch (i) { case VIEW_TYPES.Normal: rowView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.normal, viewGroup, false); break; case VIEW_TYPES.Header: rowView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.header, viewGroup, false); break; case VIEW_TYPES.Footer: rowView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.footer, viewGroup, false); break; default: rowView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.normal, viewGroup, false); break; } return new ViewHolder (rowView); }

Ahora, en el método onBindViewHolder, vincule su diseño en función del titular de la vista:

@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { int viewType = getItemViewType(position); switch(viewType) { case VIEW_TYPES.Header: // handle row header break; case VIEW_TYPES.Footer: // handle row footer break; case VIEW_TYPES.Normal: // handle row item break; } }

Espero que esto pueda ayudar.