Ich habe ListView, das eine Art von Ereignissen enthält. Ereignisse werden nach Tag sortiert, und ich möchte für jeden Tag eine Kopfzeile mit Datum haben, und dann hören die Ereignisse unten zu.
So fülle ich diese Liste:
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);
und so sieht meine Klasse TwoText aus:
public class TwoText {
public String classID;
public String state;
public TwoText(String classID, String state) {
this.classID = classID;
this.state = state;
}
}
und so sieht meine TwoTextArrayAdapter-Klasse aus:
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;
}
}
und das ist 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>
Was ich im Moment mache, ist, dass ich Header nur als reguläres Listenobjekt hinzufüge, aber ich möchte, dass es als Header ist und in meinem Fall ein Datum darauf hat.
Ich habe diesen Code in meiner XML für den Header:
<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" />
und ich habe versucht, es zu verstecken, wenn es nicht notwendig ist, und es zu zeigen, wenn es notwendig ist, aber ich habe nur den Rest meines Codes durcheinander gebracht. Ich habe noch ein paar Tutorials ausprobiert, aber sie hatten auch den gleichen Effekt.
Könnte mich jemand anleiten, wie man das so einfach macht?
Sie suchen wahrscheinlich nach einer ExpandableListView mit Überschriften (Gruppen), um Elemente (untergeordnete Elemente) zu trennen.
Schönes Tutorial zum Thema: hier .
quelle
onGroupClick
, dass nur das Klicken auf "Header" behandelt wird und Sie das Klicken oder ähnliches nicht deaktivieren müssen. Brechen Sie einfach jede Kollapsaktion ab und setzen Sie alle Gruppen von Anfang an auf "Erweitert".ExpandableListView
in den meisten Fällen am besten ist. Ich habe jedoch eine Situation, in der ich manchmal eine flache Liste und zu anderen Zeiten in meiner Aktivität eine Liste mit Überschriften anzeigen möchte. LeiderExpandableListAdapter
erweitert dieListAdapter
Schnittstelle die Schnittstelle nicht, so dass ich für Polymorphismus gezwungen bin, die Lösung von @ antew zu verwenden.Alternativ gibt es eine schöne Bibliothek von Drittanbietern, die speziell für diesen Anwendungsfall entwickelt wurde. Dabei müssen Sie Header basierend auf den im Adapter gespeicherten Daten generieren. Sie werden Rolodex-Adapter genannt und mit verwendet
ExpandableListViews
. Sie können einfach so angepasst werden, dass sie sich wie eine normale Liste mit Überschriften verhalten.Wenn Sie die
Event
Objekte des OP verwenden und wissen, dass die Header auf denDate
zugehörigen basieren, würde der Code ungefähr so aussehen:Die Aktivität
Der Adapter
quelle
Was ich getan habe, um das Datum (z. B. 01. Dezember 2016) als Header zu erstellen. Ich habe die StickyHeaderListView-Bibliothek verwendet
https://github.com/emilsjolander/StickyListHeaders
Konvertieren Sie das Datum in Millis in Long [ohne Uhrzeit] und legen Sie es als Header-ID fest.
quelle
Hier ist ein Beispielprojekt , das auf der detaillierten und hilfreichen Antwort von antew basiert und ein
ListView
mit mehreren Überschriften implementiert , das Ansichtshalter enthält, um die Bildlaufleistung zu verbessern.In diesem Projekt sind die in dargestellten Objekte
ListView
Instanzen der KlasseHeaderItem
oder der KlasseRowItem
, die beide Unterklassen der abstrakten Klasse sindItem
. Jede Unterklasse vonItem
entspricht einem anderen Ansichtstyp im benutzerdefinierten AdapterItemAdapter
. Die MethodegetView()
onItemAdapter
delegiert die Erstellung der Ansicht für jedes Listenelement an eine individualisiertegetView()
Methode für entwederHeaderItem
oderRowItem
, abhängig von derItem
Unterklasse, die an der Position verwendet wird, die an diegetView()
Methode auf dem Adapter übergeben wurde. JederItem
Unterklasse bietet einen eigenen Ansichtshalter.Die Ansichtsinhaber werden wie folgt implementiert. Die
getView()
Methoden in denItem
Unterklassen prüfen, ob dasView
Objekt, das an diegetView()
Methode übergeben wurde,ItemAdapter
null ist. In diesem Fall wird das entsprechende Layout aufgeblasen und ein Ansichtshalterobjekt wird instanziiert und der aufgeblasenen Ansicht über zugeordnetView.setTag()
. Wenn dasView
Objekt nicht null ist, wurde der Ansicht bereits ein Ansichtsinhaberobjekt zugeordnet, und der Ansichtsinhaber wird über abgerufenView.getTag()
. Die Art und Weise, wie die Ansichtshalter verwendet werden, ist im folgenden Codeausschnitt von zu sehenHeaderItem
:Die vollständige Implementierung der ListView folgt. Hier ist der Java-Code:
Es gibt auch zwei Listenelementlayouts, eines für jede Elementunterklasse. Hier ist das
header
von HeaderItem verwendete Layout:Und hier ist das
row
von RowItem verwendete Layout:Hier ist ein Bild eines Teils der resultierenden ListView:
quelle