Tengo ListView que tiene algún tipo de eventos. Los eventos están ordenados por día, y me gustaría tener un encabezado con fecha para cada día, y luego los eventos se escuchan a continuación.
Así es como llego esa lista:
ArrayList<TwoText> crs = new ArrayList<TwoText>();
crs.add(new TwoText("This will be header", event.getDate()));
for (Event event : events) {
crs.add(new TwoText(event.getStartString() + "-" + event.getEndString(), event.getSubject()));
}
arrayAdapter = new TwoTextArrayAdapter(this, R.layout.my_list_item, crs);
lv1.setAdapter(arrayAdapter);
y así es como se ve mi clase TwoText:
public class TwoText {
public String classID;
public String state;
public TwoText(String classID, String state) {
this.classID = classID;
this.state = state;
}
}
y así es como se ve mi clase TwoTextArrayAdapter:
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class TwoTextArrayAdapter extends ArrayAdapter<TwoText> {
private ArrayList<TwoText> classes;
private Activity con;
TextView seperator;
public TwoTextArrayAdapter(Activity context, int textViewResourceId, ArrayList<TwoText> classes) {
super(context, textViewResourceId, classes);
this.con = context;
this.classes = classes;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.my_list_item, null);
}
TwoText user = classes.get(position);
if (user != null) {
TextView content1 = (TextView) v.findViewById(R.id.list_content1);
TextView content2 = (TextView) v.findViewById(R.id.list_content2);
if (content1 != null) {
content1.setText(user.classID);
}
if(content2 != null) {
content2.setText(user.state);
}
}
return v;
}
}
y este es my_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
style="?android:attr/listSeparatorTextViewStyle"
android:id="@+id/separator"
android:text="Header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#757678"
android:textColor="#f5c227" />
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/list_content1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="5dip"
android:clickable="false"
android:gravity="center"
android:longClickable="false"
android:paddingBottom="1dip"
android:paddingTop="1dip"
android:text="sample"
android:textColor="#ff7f1d"
android:textSize="17dip"
android:textStyle="bold" />
<TextView
android:id="@+id/list_content2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="5dip"
android:clickable="false"
android:gravity="center"
android:linksClickable="false"
android:longClickable="false"
android:paddingBottom="1dip"
android:paddingTop="1dip"
android:text="sample"
android:textColor="#6d6d6d"
android:textSize="17dip" />
</LinearLayout>
</LinearLayout>
Lo que hago en este momento es que estoy agregando el encabezado como un objeto de lista normal, pero me gustaría que fuera como encabezado y, en mi caso, tenga una fecha.
Tengo este código en mi xml para el encabezado:
<TextView
style="?android:attr/listSeparatorTextViewStyle"
android:id="@+id/separator"
android:text="Header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#757678"
android:textColor="#f5c227" />
e intenté ocultarlo cuando no es necesario y mostrarlo cuando era necesario, pero simplemente estropeé el resto del código. Intenté algunos tutoriales más pero también tuvieron el mismo efecto.
¿Alguien podría guiarme sobre cómo hacerlo de esa manera fácil?
Probablemente esté buscando un ExpandableListView que tenga encabezados (grupos) para separar elementos (elementos secundarios).
Buen tutorial sobre el tema: aquí .
fuente
onGroupClick
que solo maneja el clic en "encabezados" y no necesita deshabilitar el clic o algo así, simplemente cancele cualquier acción de colapso y configure todos los grupos para expandirse desde el inicio.ExpandableListView
es lo mejor en la mayoría de los casos. Sin embargo, tengo una situación en la que quiero mostrar una lista plana a veces, y una lista con encabezados en otras ocasiones en mi Actividad. Lamentablemente, laExpandableListAdapter
interfaz no extiende laListAdapter
interfaz, por lo que para el polimorfismo me veo obligado a usar la solución de @ antew.Como alternativa, hay una bonita biblioteca de terceros diseñada solo para este caso de uso. Por lo tanto, debe generar encabezados basados en los datos que se almacenan en el adaptador. Se llaman adaptadores Rolodex y se usan con
ExpandableListViews
. Se pueden personalizar fácilmente para comportarse como una lista normal con encabezados.Usar los
Event
objetos del OP y saber que los encabezados se basan en loDate
asociado con él ... el código se vería así:La actividad
El adaptador
fuente
Lo que hice para hacer la Fecha (por ejemplo, 01 de diciembre de 2016) como encabezado. Usé la biblioteca StickyHeaderListView
https://github.com/emilsjolander/StickyListHeaders
Convierta la fecha a larga en milis [no incluya la hora] y conviértala como el ID del encabezado.
fuente
Aquí hay un proyecto de muestra , basado en la respuesta detallada y útil de antew, que implementa un
ListView
con múltiples encabezados que incorpora titulares de vista para mejorar el rendimiento de desplazamiento.En este proyecto, los objetos representados en el
ListView
son instancias de la claseHeaderItem
o la claseRowItem
, los cuales son subclases de la clase abstractaItem
. Cada subclase deItem
corresponde a un diferente tipo de vista en el adaptador personalizado,ItemAdapter
. El métodogetView()
enItemAdapter
delega la creación de la vista para cada elemento de la lista a ungetView()
método individualizado en cualquieraHeaderItem
oRowItem
, dependiendo de laItem
subclase utilizada en la posición pasada algetView()
método en el adaptador. CadaItem
subclase proporciona su propio soporte de vista.Los titulares de la vista se implementan de la siguiente manera. Los
getView()
métodos en lasItem
subclases verifican si elView
objeto que se pasó algetView()
métodoItemAdapter
es nulo. Si es así, se infla el diseño apropiado y se crea una instancia de un objeto titular de la vista y se asocia con la vista inflada medianteView.setTag()
. Si elView
objeto no es nulo, entonces un objeto titular de la vista ya estaba asociado con la vista, y el titular de la vista se recupera medianteView.getTag()
. La forma en que se utilizan los titulares de la vista se puede ver en el siguiente fragmento de código deHeaderItem
:La implementación completa de ListView sigue. Aquí está el código Java:
También hay dos diseños de elementos de lista, uno para cada subclase de elementos. Aquí está el diseño
header
, utilizado por HeaderItem:Y aquí está el diseño
row
, utilizado por RowItem:Aquí hay una imagen de una parte del ListView resultante:
fuente