Freigeben über


Anpassen der Darstellung eines ListView-Steuerelements mit Xamarin.Android

Die Darstellung eines ListView-Steuerelements wird durch das Layout der angezeigten Zeilen bestimmt. Verwenden Sie zum Ändern der Darstellung eines ListViewZeilenlayouts ein anderes Zeilenlayout.

Integrierte Zeilenansichten

Es gibt zwölf integrierte Ansichten, auf die mit Android.Resource.Layout verwiesen werden kann:

  • TestListItem – Einzelne Textzeile mit minimaler Formatierung.

  • SimpleListItem1 – Einzelne Textzeile.

  • SimpleListItem2 – Zwei Textzeilen.

  • SimpleSelectableListItem – Einzelne Textzeile, die die Auswahl einzelner oder mehrerer Elemente unterstützt (in API-Ebene 11 hinzugefügt).

  • SimpleListItemActivated1 – Ähnlich wie SimpleListItem1, aber die Hintergrundfarbe gibt an, wann eine Zeile ausgewählt wird (hinzugefügt in API-Ebene 11).

  • SimpleListItemActivated2 – Ähnlich wie SimpleListItem2, aber die Hintergrundfarbe gibt an, wann eine Zeile ausgewählt ist (in API-Ebene 11 hinzugefügt).

  • SimpleListItemChecked – Zeigt Häkchen an, um die Auswahl anzugeben.

  • SimpleListItemMultipleChoice – Zeigt Kontrollkästchen an, um die Mehrfachauswahl anzugeben.

  • SimpleListItemSingleChoice – Zeigt Optionsfelder an, um sich gegenseitig ausschließende Auswahl anzuzeigen.

  • TwoLineListItem – Zwei Textzeilen.

  • ActivityListItem – Einzelne Textzeile mit einem Bild.

  • SimpleExpandableListItem – Gruppiert Zeilen nach Kategorien, und jede Gruppe kann erweitert oder reduziert werden.

Jede integrierte Zeilenansicht weist eine integrierte Formatvorlage auf. Diese Screenshots zeigen, wie jede Ansicht angezeigt wird:

Screenshots von TestListItem, SimpleSelectableListItem, SimpleListitem1 und SimpleListItem2

Screenshots von

Screenshots von SimpleListItemSingleChoice, TwoLineListItem, ActivityListItem und SimpleExpandableListItem

Die BuiltInViews/HomeScreenAdapter.cs-Beispieldatei (in der BuiltInViews-Lösung ) enthält den Code, um die nicht erweiterbaren Listenelementbildschirme zu erzeugen. Die Ansicht wird in der GetView Methode wie folgt festgelegt:

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);

Die Eigenschaften der Ansicht können dann festgelegt werden, indem sie auf die Standardsteuerelement-IDs Text1verweisen, Text2 und Icon unter Android.Resource.Id (legen Sie keine Eigenschaften fest, die die Ansicht nicht enthält oder eine Ausnahme ausgelöst wird):

view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Android.Resource.Id.Text2).Text = item.SubHeading;
view.FindViewById<ImageView>(Android.Resource.Id.Icon).SetImageResource(item.ImageResourceId); // only use with ActivityListItem

Die BuiltInExpandableViews/ExpandableScreenAdapter.cs Beispieldatei (in der BuiltInViews-Lösung ) enthält den Code, um den SimpleExpandableListItem-Bildschirm zu erzeugen. Die Gruppenansicht wird in der GetGroupView Methode wie folgt festgelegt:

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem1, null);

Die untergeordnete Ansicht wird in der GetChildView Methode wie folgt festgelegt:

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem2, null);

Die Eigenschaften für die Gruppenansicht und die untergeordnete Ansicht können dann durch Verweisen auf die Standard Text1 - und Text2 Steuerelement-IDs wie oben dargestellt festgelegt werden. Der Screenshot des SimpleExpandableListItem (siehe oben) enthält ein Beispiel für eine einzeilige Gruppenansicht (SimpleExpandableListItem1) und eine zweizeilige untergeordnete Ansicht (SimpleExpandableListItem2). Alternativ kann die Gruppenansicht für zwei Zeilen (SimpleExpandableListItem2) konfiguriert werden, und die untergeordnete Ansicht kann für eine Zeile (SimpleExpandableListItem1) konfiguriert werden, oder sowohl die Gruppenansicht als auch die untergeordnete Ansicht können dieselbe Anzahl von Zeilen aufweisen.

Accessories

Zeilen können Zubehör rechts neben der Ansicht hinzugefügt werden, um den Auswahlzustand anzugeben:

  • SimpleListItemChecked – Erstellt eine Einzelauswahlliste mit einem Häkchen als Indikator.

  • SimpleListItemSingleChoice – Erstellt Optionsfeld-Typlisten, bei denen nur eine Auswahl möglich ist.

  • SimpleListItemMultipleChoice – Erstellt Kontrollkästchentyplisten, in denen mehrere Auswahlmöglichkeiten möglich sind.

Das oben genannte Zubehör wird in den folgenden Bildschirmen in ihrer jeweiligen Reihenfolge dargestellt:

Screenshots von SimpleListItemChecked, SimpleListItemSingleChoice und SimpleListItemMultipleChoice mit Zubehör

Um eins dieser Zubehörteile anzuzeigen, übergeben Sie die erforderliche Layoutressourcen-ID an den Adapter, und legen Sie dann den Auswahlstatus für die erforderlichen Zeilen manuell fest. Diese Codezeile zeigt, wie Sie eins Adapter der folgenden Layouts erstellen und zuweisen:

ListAdapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleListItemChecked, items);

Der ListView selbst unterstützt verschiedene Auswahlmodi, unabhängig vom angezeigten Zubehör. Um Verwirrung zu vermeiden, verwenden Sie Single den Auswahlmodus mit SingleChoice Zubehör und dem Checked Modus Multiple mit dem MultipleChoice Stil. Der Auswahlmodus wird durch die ChoiceMode Eigenschaft der ListView.

Behandeln der API-Ebene

In früheren Versionen von Xamarin.Android wurden Enumerationen als ganzzahlige Eigenschaften implementiert. Die neueste Version hat die richtigen .NET-Enumerationstypen eingeführt, wodurch es viel einfacher ist, die potenziellen Optionen zu ermitteln.

Je nachdem, auf welche API-Ebene Sie abzielen, ChoiceMode handelt es sich entweder um eine ganze Zahl oder eine Enumeration. Die Beispieldatei AccessoryViews/HomeScreen.cs hat einen Block auskommentiert, wenn Sie die Gingerbread-API als Ziel festlegen möchten:

// For targeting Gingerbread the ChoiceMode is an int, otherwise it is an
// enumeration.

lv.ChoiceMode = Android.Widget.ChoiceMode.Single; // 1
//lv.ChoiceMode = Android.Widget.ChoiceMode.Multiple; // 2
//lv.ChoiceMode = Android.Widget.ChoiceMode.None; // 0

// Use this block if targeting Gingerbread or lower
/*
lv.ChoiceMode = 1; // Single
//lv.ChoiceMode = 0; // none
//lv.ChoiceMode = 2; // Multiple
//lv.ChoiceMode = 3; // MultipleModal
*/

Programmgesteuertes Auswählen von Elementen

Das manuelle Festlegen, welche Elemente "ausgewählt" sind, erfolgt mit der SetItemChecked Methode (es kann mehrmals für mehrfache Auswahl aufgerufen werden):

// Set the initially checked row ("Fruits")
lv.SetItemChecked(1, true);

Der Code muss auch einzelne Auswahlen anders erkennen als mehrfache Auswahlen. Um zu bestimmen, welche Zeile im Single Modus ausgewählt wurde, verwenden Sie die CheckedItemPosition ganzzahlige Eigenschaft:

FindViewById<ListView>(Android.Resource.Id.List).CheckedItemPosition

Um zu ermitteln, welche Zeilen im Multiple Modus ausgewählt wurden, müssen Sie die CheckedItemPositions SparseBooleanArraySchleife durchlaufen. Ein geringes Array ist wie ein Wörterbuch, das nur Einträge enthält, bei denen der Wert geändert wurde. Daher müssen Sie das gesamte Array true durchlaufen, um nach Werten zu suchen, um zu wissen, was in der Liste ausgewählt wurde, wie im folgenden Codeausschnitt veranschaulicht:

var sparseArray = FindViewById<ListView>(Android.Resource.Id.List).CheckedItemPositions;
for (var i = 0; i < sparseArray.Size(); i++ )
{
   Console.Write(sparseArray.KeyAt(i) + "=" + sparseArray.ValueAt(i) + ",");
}
Console.WriteLine();

Erstellen von benutzerdefinierten Zeilenlayouts

Die vier integrierten Zeilenansichten sind sehr einfach. Um komplexere Layouts (z. B. eine Liste von E-Mails oder Tweets oder Kontaktinformationen) anzuzeigen, ist eine benutzerdefinierte Ansicht erforderlich. Benutzerdefinierte Ansichten werden im Allgemeinen als AXML-Dateien im Verzeichnis "Ressourcen/Layout " deklariert und dann mithilfe ihrer Ressourcen-ID von einem benutzerdefinierten Adapter geladen. Die Ansicht kann eine beliebige Anzahl von Anzeigeklassen (z. B. TextViews, ImageViews und andere Steuerelemente) mit benutzerdefinierten Farben, Schriftarten und Layout enthalten.

Dieses Beispiel unterscheidet sich von den vorherigen Beispielen auf verschiedene Arten:

  • Erbt von Activity , nicht ListActivity . Sie können Zeilen für beliebige ListView Steuerelemente anpassen, andere Steuerelemente können jedoch auch in ein Activity Layout aufgenommen werden (z. B. Überschriften, Schaltflächen oder andere Benutzeroberflächenelemente). In diesem Beispiel wird oberhalb der ListView zu veranschaulichenden Überschrift eine Überschrift hinzugefügt.

  • Erfordert eine AXML-Layoutdatei für den Bildschirm; in den vorherigen Beispielen ListActivity ist keine Layoutdatei erforderlich. Diese AXML enthält eine ListView Steuerelementdeklaration.

  • Erfordert eine AXML-Layoutdatei zum Rendern jeder Zeile. Diese AXML-Datei enthält die Text- und Bildsteuerelemente mit benutzerdefinierten Schriftart- und Farbeinstellungen.

  • Verwendet eine optionale benutzerdefinierte Selektor-XML-Datei, um die Darstellung der Zeile festzulegen, wenn sie ausgewählt ist.

  • Die Adapter Implementierung gibt ein benutzerdefiniertes Layout aus der GetView Außerkraftsetzung zurück.

  • ItemClickmuss anders deklariert werden (ein Ereignishandler wird anstelle einer Außerkraftsetzung OnListItemClick angefügt ListView.ItemClick ListActivity).

Diese Änderungen sind unten detailliert dargestellt, beginnend mit dem Erstellen der Ansicht der Aktivität und der benutzerdefinierten Zeilenansicht und anschließender Abdeckung der Änderungen am Adapter und der Aktivität, um sie zu rendern.

Hinzufügen einer ListView zu einem Aktivitätslayout

Da HomeScreen sie nicht mehr über eine Standardansicht erbt ListActivity , muss daher eine Layout-AXML-Datei für die HomeScreen-Ansicht erstellt werden. In diesem Beispiel verfügt die Ansicht über eine Überschrift (mit einer TextView) und eine ListView zum Anzeigen von Daten. Das Layout ist in der Datei "Resources/Layout/HomeScreen.axml " definiert, die hier gezeigt wird:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
    <TextView android:id="@+id/Heading"
        android:text="Vegetable Groups"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        android:textSize="30dp"
        android:textColor="#FF267F00"
        android:textStyle="bold"
        android:padding="5dp"
    />
    <ListView android:id="@+id/List"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:cacheColorHint="#FFDAFF7F"
    />
</LinearLayout>

Der Vorteil der Verwendung eines Activity benutzerdefinierten Layouts (anstelle eines ListActivity) liegt darin, dem Bildschirm zusätzliche Steuerelemente hinzuzufügen, z. B. die Überschrift TextView in diesem Beispiel.

Erstellen eines benutzerdefinierten Zeilenlayouts

Eine weitere AXML-Layoutdatei ist erforderlich, um das benutzerdefinierte Layout für jede Zeile zu enthalten, die in der Listenansicht angezeigt wird. In diesem Beispiel enthält die Zeile einen grünen Hintergrund, braunen Text und rechts ausgerichtetes Bild. Das Android-XML-Markup zum Deklarieren dieses Layouts wird in "Resources/Layout/CustomView.axml" beschrieben:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:background="#FFDAFF7F"
   android:padding="8dp">
    <LinearLayout android:id="@+id/Text"
       android:orientation="vertical"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:paddingLeft="10dip">
        <TextView
         android:id="@+id/Text1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textColor="#FF7F3300"
         android:textSize="20dip"
         android:textStyle="italic"
         />
        <TextView
         android:id="@+id/Text2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textSize="14dip"
         android:textColor="#FF267F00"
         android:paddingLeft="100dip"
         />
    </LinearLayout>
    <ImageView
        android:id="@+id/Image"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:padding="5dp"
        android:src="@drawable/icon"
        android:layout_alignParentRight="true" />
</RelativeLayout >

Während ein benutzerdefiniertes Zeilenlayout viele verschiedene Steuerelemente enthalten kann, kann die Bildlaufleistung durch komplexe Designs und die Verwendung von Bildern beeinflusst werden (insbesondere, wenn sie über das Netzwerk geladen werden müssen). Weitere Informationen zur Behandlung von Leistungsproblemen beim Scrollen finden Sie im Google-Artikel.

Verweisen auf eine benutzerdefinierte Zeilenansicht

Die Implementierung des benutzerdefinierten Adapterbeispiels ist in HomeScreenAdapter.cs. Die Schlüsselmethode ist GetView der Ort, an dem die benutzerdefinierte AXML mithilfe der Ressourcen-ID Resource.Layout.CustomViewgeladen wird, und legt dann Eigenschaften für jedes der Steuerelemente in der Ansicht fest, bevor sie zurückgegeben wird. Die vollständige Adapterklasse wird angezeigt:

public class HomeScreenAdapter : BaseAdapter<TableItem> {
   List<TableItem> items;
   Activity context;
   public HomeScreenAdapter(Activity context, List<TableItem> items)
       : base()
   {
       this.context = context;
       this.items = items;
   }
   public override long GetItemId(int position)
   {
       return position;
   }
   public override TableItem this[int position]
   {
       get { return items[position]; }
   }
   public override int Count
   {
       get { return items.Count; }
   }
   public override View GetView(int position, View convertView, ViewGroup parent)
   {
       var item = items[position];
       View view = convertView;
       if (view == null) // no view to re-use, create new
           view = context.LayoutInflater.Inflate(Resource.Layout.CustomView, null);
       view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
       view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;
       view.FindViewById<ImageView>(Resource.Id.Image).SetImageResource(item.ImageResourceId);
       return view;
   }
}

Verweisen auf die benutzerdefinierte ListView in der Aktivität

Da die HomeScreen Klasse jetzt von Activityerbt, wird ein ListView Feld in der Klasse deklariert, um einen Verweis auf das im AXML deklarierte Steuerelement zu enthalten:

ListView listView;

Die Klasse muss dann das benutzerdefinierte Layout "AXML" der Aktivität mithilfe der SetContentView Methode laden. Anschließend wird das ListView Steuerelement im Layout erstellt und zugewiesen und dem Klickhandler zugewiesen. Der Code für die OnCreate-Methode wird hier gezeigt:

SetContentView(Resource.Layout.HomeScreen); // loads the HomeScreen.axml as this activity's view
listView = FindViewById<ListView>(Resource.Id.List); // get reference to the ListView in the layout

// populate the listview with data
listView.Adapter = new HomeScreenAdapter(this, tableItems);
listView.ItemClick += OnListItemClick;  // to be defined

Schließlich muss der ItemClick Handler definiert werden. In diesem Fall wird nur eine Toast Meldung angezeigt:

void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
   var listView = sender as ListView;
   var t = tableItems[e.Position];
   Android.Widget.Toast.MakeText(this, t.Heading, Android.Widget.ToastLength.Short).Show();
}

Der resultierende Bildschirm sieht wie folgt aus:

Screenshot der resultierenden CustomRowView

Anpassen der Zeilenauswahlfarbe

Wenn eine Zeile berührt wird, sollte sie für Benutzerfeedback hervorgehoben werden. Wenn eine benutzerdefinierte Ansicht als Hintergrundfarbe wie CustomView.axml angibt, überschreibt sie auch die Auswahlherhebung. Diese Codezeile in CustomView.axml legt den Hintergrund auf Hellgrün fest, bedeutet aber auch, dass es keinen visuellen Indikator gibt, wenn die Zeile berührt wird:

android:background="#FFDAFF7F"

Um das Hervorhebungsverhalten erneut zu aktivieren und die verwendete Farbe anzupassen, legen Sie stattdessen das Hintergrundattribute auf eine benutzerdefinierte Auswahl fest. Die Auswahl deklariert sowohl die Standardhintergrundfarbe als auch die Hervorhebungsfarbe. Die Datei "Resources/Drawable/CustomSelector.xml " enthält die folgende Deklaration:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"
  android:state_selected="false"
  android:drawable="@color/cellback" />
<item android:state_pressed="true" >
  <shape>
     <gradient
      android:startColor="#E77A26"
        android:endColor="#E77A26"
        android:angle="270" />
  </shape>
</item>
<item android:state_selected="true"
  android:state_pressed="false"
  android:drawable="@color/cellback" />
</selector>

Um auf die benutzerdefinierte Auswahl zu verweisen, ändern Sie das Hintergrundattribute in CustomView.axml in:

android:background="@drawable/CustomSelector"

Eine ausgewählte Zeile und die entsprechende Toast Nachricht sieht nun wie folgt aus:

Eine ausgewählte Zeile in Orange, wobei die Popupmeldung den Namen der ausgewählten Zeile anzeigt

Verhindern von Flackern in benutzerdefinierten Layouts

Android versucht, die Leistung des ListView Bildlaufs zu verbessern, indem Layoutinformationen zwischengespeichert werden. Wenn Sie über lange Bildlauflisten mit Daten verfügen, sollten Sie auch die Eigenschaft für die android:cacheColorHint ListView Deklaration in der AXML-Definition der Aktivität festlegen (auf denselben Farbwert wie der Hintergrund des benutzerdefinierten Zeilenlayouts). Wenn dieser Hinweis nicht eingeschlossen werden kann, kann ein "Flackern" auftreten, wenn der Benutzer durch eine Liste mit benutzerdefinierten Zeilenhintergrundfarben scrollt.