Estoy buscando un equivalente a addHeaderView para una vista de reciclador. Básicamente, quiero que se agregue una imagen con 2 botones como encabezado a la vista de lista. ¿Hay alguna forma diferente de agregar una vista de encabezado a una vista de reciclador? Un ejemplo de orientación sería útil.
EDIT 2 (diseños de fragmentos añadidos):
Después de agregar declaraciones de registro, parece que getViewType solo recibe una posición de 0. Esto lleva a que onCreateView solo cargue un diseño:
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemCount: 5
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> getItemViewType position: 0
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> onCreateViewHolder, viewtype: 0
10-26 16:32:53.766 5449-5449/co.testapp I/logger info﹕ Adapter-> onBindViewHolder, viewType: 0
La transición del fragmento para cargar el fragmento de comentario:
@Override
public void onPhotoFeedItemClick(View view, int position) {
if (fragmentManager == null)
fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (view.getId() == R.id.button_comment){
CommentFragment commentFragment = CommentFragment.newInstance("","", position);
fragmentTransaction.add(R.id.main_activity, commentFragment,"comment_fragment_tag");
fragmentTransaction.addToBackStack(Constants.TAG_COMMENTS);
fragmentTransaction.commit();
}
}
OnCreateView de The Fragment:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_comment, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.list_recylclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(_context));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mAdapter = new CommentAdapter(R.layout.row_list_comments, R.layout.row_header_comments, _context, comments);
mRecyclerView.setAdapter(mAdapter);
return view;
}
El fragmento que contiene la vista de reciclaje:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context="co.testapp.fragments.CommentFragment"
android:background="@color/white">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_recylclerview"
android:layout_width="match_parent"
android:layout_height="200dp" />
</RelativeLayout>
</RelativeLayout>
El diseño de la fila de comentarios:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_margin="10dp"
android:background="@color/white">
<!--Profile Picture-->
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/profile_picture"
android:background="@color/blue_testapp"/>
<!--Name-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="First Name Last Name"
android:textSize="16dp"
android:textColor="@color/blue_testapp"
android:id="@+id/name_of_poster"
android:layout_toRightOf="@id/profile_picture"
/>
<!--Comment-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_marginTop="-5dp"
android:text="This is a test comment"
android:textSize="14dp"
android:textColor="@color/black"
android:id="@+id/comment"
android:layout_below="@id/name_of_poster"
android:layout_toRightOf="@id/profile_picture"/>
</RelativeLayout>
El encabezado
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="300dp"
android:id="@+id/header_photo"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
El código del adaptador (gracias a hister por comenzar):
public class CommentAdapter extends RecyclerView.Adapter<ViewHolder>{
private final int rowCardLayout;
public static Context mContext;
private final int headerLayout;
private final String [] comments;
private static final int HEADER = 0;
private static final int OTHER = 0;
public CommentAdapter(int rowCardLayout, int headerLayout, Context context, String [] comments) {
this.rowCardLayout = rowCardLayout;
this.mContext = context;
this.comments = comments;
this.headerLayout = headerLayout;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
logger.i("onCreateViewHolder, viewtype: " + i); //viewtype always returns 0 so OTHER layout is never inflated
if (i == HEADER) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(headerLayout, viewGroup, false);
return new ViewHolderHeader(v);
}
else if (i == OTHER){
View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowCardLayout, viewGroup, false);
return new ViewHolderComments(v);
}
else
throw new RuntimeException("Could not inflate layout");
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
logger.i("onBindViewHolder, viewType: " + i);
if (viewHolder instanceof ViewHolderComments)
((ViewHolderComments) viewHolder).comment.setText(comments[i].toString());
if (viewHolder instanceof ViewHolderHeader)
((ViewHolderHeader) viewHolder).header.setImageResource(R.drawable.image2);
else {
logger.e("no instance of viewholder found");
}
}
@Override
public int getItemCount() {
int count = comments.length + 1;
logger.i("getItemCount: " + count);
return count;
}
@Override
public int getItemViewType(int position) {
logger.i("getItemViewType position: " + position);
if (position == HEADER)
return HEADER;
else
return OTHER;
}
public static class ViewHolderComments extends RecyclerView.ViewHolder {
public TextView comment;
public ImageView image;
public ViewHolderComments(View itemView) {
super(itemView);
comment = (TextView) itemView.findViewById(R.id.comment);
image = (ImageView) itemView.findViewById(R.id.image);
}
}
public static class ViewHolderHeader extends RecyclerView.ViewHolder {
public final ImageView header;
public ViewHolderHeader(View itemView){
super(itemView);
header = (ImageView) itemView.findViewById(R.id.header_photo);
}
}
}
Usando el código anterior, sólo el diseño de cabecera se muestra como ViewType es siempre 0. Parece que este . Si fuerzo otro diseño parece que esto :
fuente
Respuestas:
No hay una manera fácil de hacerlo,
listview.addHeaderView()
pero puede lograrlo agregando un tipo a su adaptador para el encabezado.Aquí hay un ejemplo
enlace a la esencia -> aquí
fuente
private String getItem(int position) { return data[position + 1]; }
Causa una NPE. Como nuestra posición se ha incrementado en uno, debido al encabezado, tenemos que restar 1 para obtener el elemento correcto de nuestros datos [].private String getItem(int position) { return data[position - 1]; }
setSpanSizeLookup
paraGridLayoutManager
, además , su encabezado tomará todas las columnasFácil y reutilizable
ItemDecoration
Los encabezados estáticos se pueden agregar fácilmente con
ItemDecoration
y sin más cambios.La decoración también es reutilizable, ya que no hay necesidad de modificar el adaptador o del
RecyclerView
todo.El código de muestra proporcionado a continuación requerirá una vista para agregar a la parte superior que se puede inflar como todo lo demás. Puede verse así:
¿Por qué estático ?
Si solo tiene que mostrar texto e imágenes, esta solución es para usted: no existe la posibilidad de interacción del usuario, como botones o ver localizadores, ya que solo aparecerá en la parte superior de su lista.
Manejo de lista vacía
Si no hay vista para decorar, la decoración no se dibujará. Aún tendrá que manejar una lista vacía usted mismo. (Una posible solución sería agregar un elemento ficticio al adaptador).
El código
Puede encontrar el código fuente completo aquí en GitHub, incluido a
Builder
para ayudar con la inicialización del decorador, o simplemente use el código a continuación y proporcione sus propios valores al constructor.Asegúrese de establecer una correcta
layout_height
para su vista. Por ejemplo,match_parent
podría no funcionar correctamente.Tenga en cuenta: El proyecto GitHub es mi patio de recreo personal. No se prueba thorougly, por lo que no hay ninguna biblioteca todavía .
¿Qué hace?
Un
ItemDecoration
es un dibujo adicional a un elemento de una lista. En este caso, se dibuja una decoración en la parte superior del primer elemento.La vista se mide y se presenta, luego se dibuja en la parte superior del primer elemento. Si se agrega un efecto de paralaje, también se recortará a los límites correctos.
fuente
Siéntase libre de usar mi biblioteca, disponible aquí .
Le permite crear un encabezado
View
para cualquieraRecyclerView
que lo useLinearLayoutManager
oGridLayoutManager
con solo una simple llamada al método.fuente
Voy a mostrarle que haga un encabezado con elementos en una vista de Reciclador.
Paso 1- Agregue dependencia a su archivo gradle.
Cardview se utiliza con fines decorativos.
Paso 2: crea tres archivos xml. Uno para la actividad principal. Segundo para el diseño del encabezado. Tercero para el diseño del elemento de la lista.
activity_main.xml
header.xml
list.xml
Paso 3- Crea tres clases de frijoles.
Header.java
ContentItem.java
ListItem.java
Paso 4- Cree un adaptador llamado MyRecyclerAdapter.java
Paso 5- En MainActivity agregue el siguiente código:
La función getList () genera dinámicamente los datos para los encabezados y para los elementos de la lista.
fuente
Puede lograrlo usando 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:
2) Cree un ViewHolder personalizado para los elementos:
3) Configure su ReclyclerView con el SectionedRecyclerViewAdapter
fuente
Simplemente puede colocar su encabezado y su RecyclerView en un NestedScrollView:
Para que el desplazamiento funcione correctamente, debe deshabilitar el desplazamiento anidado en su RecyclerView:
fuente
La API nativa no tiene esa función "addHeader", pero tiene el concepto de "addItem".
Pude incluir esta característica específica de encabezados y extensiones para pies de página también en mi proyecto FlexibleAdapter . Lo llamé encabezados y pies de página desplazables .
Aquí cómo funcionan:
Los encabezados y pies de página desplazables son elementos especiales que se desplazan junto con todos los demás, pero no pertenecen a los elementos principales (elementos comerciales) y siempre los maneja el adaptador junto a los elementos principales. Esos artículos se encuentran persistentemente en la primera y última posición.
Hay mucho que decir sobre ellos, mejor leer la página wiki detallada .
Además, el Adaptador flexible le permite crear encabezados / secciones, también puede tenerlos adhesivos y decenas de otras características como elementos expandibles, desplazamiento sin fin, extensiones de interfaz de usuario, etc. ¡todo en una biblioteca!
fuente
Basado en esta publicación , creé una subclase de RecyclerView.Adapter que admite una cantidad arbitraria de encabezados y pies de página.
https://gist.github.com/mheras/0908873267def75dc746
Aunque parece ser una solución, también creo que esto debería ser administrado por LayoutManager. Desafortunadamente, lo necesito ahora y no tengo tiempo para implementar un StaggeredGridLayoutManager desde cero (ni siquiera extenderlo).
Todavía lo estoy probando, pero puedes probarlo si quieres. Avíseme si encuentra algún problema con él.
fuente
Hay una solución más que cubre todos los casos de uso anteriores: Adaptador compuesto: https://github.com/negusoft/CompoundAdapter-android
Puede crear un Grupo de adaptadores que contenga su Adaptador tal como está, junto con un adaptador con un solo elemento para representar el encabezado. El código es fácil y legible:
AdapterGroup también permite el anidamiento, por lo que para un adaptador con secciones, puede crear un AdapterGroup por sección. Luego, coloque todas las secciones en un grupo de adaptadores raíz.
fuente
HeaderView depende del LayoutManager. Ninguno de los LayoutManagers predeterminados admite esto y probablemente no lo hará. HeaderView en ListView crea mucha complejidad sin ningún beneficio significativo.
Sugeriría crear una clase de adaptador base que agregue elementos para encabezados si se proporciona. No olvide anular los métodos de notificación * para compensarlos correctamente dependiendo de si el encabezado está presente o no.
fuente
ListView.addHeaderView
la respuesta a esta pregunta.Después: anula el método getItemViewTpe *** Más importante
método onCreateViewHolder
método onBindViewHolder
en finaliza implementa la clase ViewHolders estática
fuente
aquí alguna decoración del artículo para la vista del reciclador
fuente
Hice una implementación basada en la de @ hister para mis propósitos personales, pero usando herencia.
Oculto los mecanismos de detalles de implementación (como sumar 1 a
itemCount
, restar 1 deposition
) en una superclase abstractaHeadingableRecycleAdapter
, implementando los métodos requeridos de Adaptador comoonBindViewHolder
,getItemViewType
ygetItemCount
haciendo que esos métodos sean finales y proporcionando nuevos métodos con lógica oculta al cliente:onAddViewHolder(RecyclerView.ViewHolder holder, int position)
,onCreateViewHolder(ViewGroup parent)
,itemCount()
Aquí están la
HeadingableRecycleAdapter
clase y un cliente. Dejé el diseño del encabezado un poco codificado porque se ajusta a mis necesidades.fuente
Tal vez envuelva el encabezado y la vista del reciclador en una distribución del coordinador :
fuente
Probablemente http://alexzh.com/tutorials/multiple-row-layouts-using-recyclerview/ ayudará. Utiliza solo RecyclerView y CardView. Aquí hay un adaptador:
Y aquí hay una entidad:
fuente
puedes crear addHeaderView y usar
adapter.addHeaderView(View)
.Este código crea el
addHeaderView
para más de un encabezado. los encabezados deberían tener:android:layout_height="wrap_content"
fuente
Han pasado algunos años, pero por si alguien está leyendo esto más tarde ...
El problema está en la declaración constante:
Si los declaras a ambos como cero, ¡siempre obtendrás cero!
fuente
He implementado el mismo enfoque propuesto por la respuesta EC84B4 , pero abstraje RecycleViewAdapter y lo hago fácilmente valioso por medio de interfaces.
Entonces, para usar mi enfoque, debe agregar las siguientes clases base e interfaces a su proyecto:
1) Interfaz que proporciona datos para el adaptador (recopilación de tipo genérico T y parámetros adicionales (si es necesario) de tipo genérico P)
2) Fábrica para atar sus artículos (encabezado / artículo):
3) Fábrica para viewHolders (encabezado / artículos):
4) Clase base para adaptador con encabezado:
Ejemplo de uso :
1) Implementación IRecycleViewListHolder:
2) Implementación IViewHolderBinderFactory:
3) Implementación IViewHolderFactory:
4) Adaptador de derivación
5) Clase de adaptador de instancia:
PD : AssetItemViewHolder, AssetBasedListItemBinding, etc. las estructuras propias de mi aplicación que deben ser intercambiadas por usted, para sus propios fines.
fuente