Udostępnij za pośrednictwem


Dostosowywanie wyglądu elementu ListView za pomocą platformy Xamarin.Android

Wygląd elementu ListView jest dyktowany przez układ wyświetlanych wierszy. Aby zmienić wygląd obiektu ListView, użyj innego układu wiersza.

Wbudowane widoki wierszy

Istnieje dwanaście wbudowanych widoków, do których można się odwoływać przy użyciu elementu Android.Resource.Layout:

  • TestListItem — pojedynczy wiersz tekstu z minimalnym formatowaniem.

  • SimpleListItem1 — pojedynczy wiersz tekstu.

  • SimpleListItem2 — dwa wiersze tekstu.

  • SimpleSelectableListItem — pojedynczy wiersz tekstu obsługujący wybór pojedynczego lub wielu elementów (dodany w interfejsie API poziom 11).

  • SimpleListItemActivated1 — podobnie jak SimpleListItem1, ale kolor tła wskazuje, kiedy jest zaznaczony wiersz (dodany w interfejsie API poziom 11).

  • SimpleListItemActivated2 — podobnie jak SimpleListItem2, ale kolor tła wskazuje, kiedy jest zaznaczony wiersz (dodany w interfejsie API poziom 11).

  • SimpleListItemChecked — wyświetla znaczniki wyboru wskazujące wybór.

  • SimpleListItemMultipleChoice — wyświetla pola wyboru wskazujące wybór wielokrotny.

  • SimpleListItemSingleChoice — wyświetla przyciski radiowe wskazujące wzajemnie wykluczające się zaznaczenie.

  • TwoLineListItem — dwa wiersze tekstu.

  • ActivityListItem — pojedynczy wiersz tekstu z obrazem.

  • SimpleExpandableListItem — grupuje wiersze według kategorii, a każda grupa może zostać rozwinięta lub zwinięta.

Każdy wbudowany widok wierszy ma wbudowany styl skojarzony z nim. Te zrzuty ekranu pokazują, jak wygląda każdy widok:

Zrzuty ekranu elementów TestListItem, SimpleSelectableListItem, SimpleListitem1 i SimpleListItem2

Zrzuty ekranu simpleListItemActivated1, SimpleListItemActivated2, SimpleListItemChecked i SimpleListItemMultipleChecked

Zrzuty ekranu simpleListItemSingleChoice, TwoLineListItem, ActivityListItem i SimpleExpandableListItem

Przykładowy plik BuiltInViews/HomeScreenAdapter.cs (w rozwiązaniu BuiltInViews ) zawiera kod umożliwiający wygenerowanie ekranów elementów listy, które nie można rozszerzać. Widok jest ustawiany w metodzie GetView w następujący sposób:

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

Właściwości widoku można następnie ustawić, odwołując się do standardowych identyfikatorów Text1kontrolek i Text2 Icon w obszarze Android.Resource.Id (nie ustawiaj właściwości, których widok nie zawiera, lub zostanie zgłoszony wyjątek):

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

Przykładowy plik BuiltInExpandableViews/ExpandableScreenAdapter.cs (w rozwiązaniu BuiltInViews ) zawiera kod umożliwiający wygenerowanie ekranu SimpleExpandableListItem. Widok grupy jest ustawiany w metodzie GetGroupView w następujący sposób:

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

Widok podrzędny jest ustawiany w metodzie GetChildView w następujący sposób:

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

Właściwości widoku grupy i widoku podrzędnego można następnie ustawić, odwołując się do identyfikatorów standardowych Text1 i Text2 kontrolnych, jak pokazano powyżej. Zrzut ekranu SimpleExpandableListItem (pokazany powyżej) przedstawia przykład widoku grupy jednowierszowej (SimpleExpandableListItem1) i dwuwierszowego widoku podrzędnego (SimpleExpandableListItem2). Alternatywnie widok grupy można skonfigurować dla dwóch wierszy (SimpleExpandableListItem2), a widok podrzędny można skonfigurować dla jednego wiersza (SimpleExpandableListItem1) lub widok grupy i widok podrzędny może mieć taką samą liczbę wierszy.

Akcesoria

Wiersze mogą mieć akcesoria dodane z prawej strony widoku, aby wskazać stan wyboru:

  • SimpleListItemChecked — tworzy listę z pojedynczym wyborem z sprawdzeniem jako wskaźnikiem.

  • SimpleListItemSingleChoice — tworzy listy typów przycisków radiowych, w których jest możliwy tylko jeden wybór.

  • SimpleListItemMultipleChoice — tworzy listy typów pól wyboru, w których można wybrać wiele opcji.

Wyżej wymienione akcesoria są ilustrowane na następujących ekranach w odpowiedniej kolejności:

Zrzuty ekranu simpleListItemChecked, SimpleListItemSingleChoice i SimpleListItemMultipleChoice z akcesoriami

Aby wyświetlić jedno z tych akcesoriów, przekaż wymagany identyfikator zasobu układu do karty, a następnie ręcznie ustaw stan zaznaczenia dla wymaganych wierszy. W tym wierszu kodu pokazano, jak utworzyć i przypisać Adapter obiekt przy użyciu jednego z następujących układów:

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

Sama ListView aplikacja obsługuje różne tryby wyboru, niezależnie od wyświetlanego akcesorium. Aby uniknąć nieporozumień, należy użyć Single trybu wyboru z akcesoriami SingleChoice i Checked trybem lub Multiple w MultipleChoice stylu. Tryb zaznaczenia jest kontrolowany ChoiceMode przez właściwość ListView.

Obsługa poziomu interfejsu API

Wcześniejsze wersje platformy Xamarin.Android zaimplementowały wyliczenia jako właściwości liczb całkowitych. Najnowsza wersja wprowadziła odpowiednie typy wyliczenia platformy .NET, co znacznie ułatwia odnajdywanie potencjalnych opcji.

W zależności od docelowego poziomu ChoiceMode interfejsu API jest liczbą całkowitą lub wyliczeniem. Przykładowy plik AccessoryViews/HomeScreen.cs ma zablokowany komentarz, jeśli chcesz kierować do interfejsu API Gingerbread:

// 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
*/

Programowe wybieranie elementów

Ręczne ustawienie, które elementy są zaznaczone, jest wykonywane za pomocą metody (można ją wywołać wiele razy w przypadku wielokrotnego SetItemChecked zaznaczenia):

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

Kod musi również wykrywać pojedyncze zaznaczenia różni się od wielu zaznaczeń. Aby określić, który wiersz został wybrany w Single trybie, użyj właściwości liczby całkowitej CheckedItemPosition :

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

Aby określić, które wiersze zostały wybrane w Multiple trybie, należy wykonać pętlę za pośrednictwem elementu CheckedItemPositions SparseBooleanArray. Tablica rozrzedzonych jest jak słownik, który zawiera tylko wpisy, w których wartość została zmieniona, więc musisz przejść przez całą tablicę szukającą true wartości, aby wiedzieć, co zostało wybrane na liście, jak pokazano w poniższym fragmencie kodu:

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();

Tworzenie niestandardowych układów wierszy

Cztery wbudowane widoki wierszy są bardzo proste. Aby wyświetlić bardziej złożone układy (takie jak lista wiadomości e-mail lub tweety lub informacje kontaktowe), wymagany jest widok niestandardowy. Widoki niestandardowe są zwykle deklarowane jako pliki AXML w katalogu Resources/Layout , a następnie ładowane przy użyciu identyfikatora zasobu przez kartę niestandardową. Widok może zawierać dowolną liczbę klas wyświetlania (takich jak TextViews, ImageViews i inne kontrolki) z niestandardowymi kolorami, czcionkami i układem.

Ten przykład różni się od poprzednich przykładów na wiele sposobów:

  • Dziedziczy z Activity , a nie ListActivity . Można dostosować wiersze dla dowolnego ListView elementu , jednak inne kontrolki można również uwzględnić w Activity układzie (na przykład nagłówek, przyciski lub inne elementy interfejsu użytkownika). W tym przykładzie dodano nagłówek powyżej elementu , aby zilustrować ListView .

  • Wymaga pliku układu AXML dla ekranu; w poprzednich przykładach ListActivity plik układu nie wymaga pliku układu. Ten kod AXML zawiera deklarację kontrolki ListView .

  • Wymaga pliku układu AXML do renderowania każdego wiersza. Ten plik AXML zawiera kontrolki tekstu i obrazu z niestandardowymi ustawieniami czcionek i kolorów.

  • Używa opcjonalnego pliku XML selektora niestandardowego, aby ustawić wygląd wiersza po jej wybraniu.

  • Implementacja Adapter zwraca niestandardowy układ z GetView przesłonięcia.

  • ItemClick program obsługi zdarzeń musi być zadeklarowany inaczej (program obsługi zdarzeń jest dołączony do ListView.ItemClick elementu , a nie do zastępowania OnListItemClick w pliku ListActivity).

Te zmiany zostały szczegółowo opisane poniżej, począwszy od utworzenia widoku działania i niestandardowego widoku wiersza, a następnie zakrywania modyfikacji adaptera i działania w celu ich renderowania.

Dodawanie elementu ListView do układu działania

Ponieważ HomeScreen nie dziedziczy ListActivity już z niego widoku domyślnego, dlatego należy utworzyć plik AXML układu dla widoku Ekranu głównego. W tym przykładzie widok będzie miał nagłówek (przy użyciu znaku TextView) i element , ListView aby wyświetlić dane. Układ jest zdefiniowany w pliku Resources/Layout/HomeScreen.axml , który jest pokazany tutaj:

<?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>

Zaletą używania Activity elementu z układem niestandardowym (zamiast ListActivity) jest możliwość dodawania dodatkowych kontrolek do ekranu, takich jak nagłówek TextView w tym przykładzie.

Tworzenie niestandardowego układu wiersza

Inny plik układu AXML jest wymagany do przechowywania niestandardowego układu dla każdego wiersza, który będzie wyświetlany w widoku listy. W tym przykładzie wiersz będzie miał zielone tło, brązowy tekst i obraz wyrównany do prawej. Znacznik XML systemu Android do deklarowania tego układu jest opisany w artykule Resources/Layout/CustomView.axml:

<?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 >

Chociaż niestandardowy układ wiersza może zawierać wiele różnych kontrolek, wydajność przewijania może mieć wpływ na złożone projekty i używanie obrazów (zwłaszcza jeśli trzeba je załadować za pośrednictwem sieci). Zobacz artykuł firmy Google, aby uzyskać więcej informacji na temat rozwiązywania problemów z wydajnością przewijania.

Odwoływanie się do niestandardowego widoku wiersza

Implementacja przykładu karty niestandardowej znajduje się w pliku HomeScreenAdapter.cs. Metoda klucza polega GetView na tym, że ładuje niestandardowy kod AXML przy użyciu identyfikatora Resource.Layout.CustomViewzasobu , a następnie ustawia właściwości dla każdego z kontrolek w widoku przed zwróceniem go. Zostanie wyświetlona kompletna klasa adaptera:

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;
   }
}

Odwoływanie się do elementu ListView niestandardowego w działaniu

HomeScreen Ponieważ klasa dziedziczy teraz z Activityklasy , ListView pole jest deklarowane w klasie w celu przechowywania odwołania do kontrolki zadeklarowanej w AXML:

ListView listView;

Klasa musi następnie załadować niestandardowy układ AXML działania przy użyciu SetContentView metody . Następnie może znaleźć kontrolkę ListView w układzie, a następnie utworzy i przypisze kartę i przypisze procedurę obsługi kliknięć. Kod metody OnCreate jest pokazany tutaj:

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

Na koniec należy zdefiniować procedurę ItemClick obsługi. W tym przypadku po prostu wyświetla Toast komunikat:

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();
}

Wynikowy ekran wygląda następująco:

Zrzut ekranu przedstawiający wynikowy element CustomRowView

Dostosowywanie koloru selektora wierszy

Po dotknięciu wiersza powinien zostać wyróżniony w celu uzyskania opinii użytkowników. Gdy widok niestandardowy określa jako kolor tła, jak robi to CustomView.axml , zastępuje również wyróżnienie zaznaczenia. Ten wiersz kodu w pliku CustomView.axml ustawia tło na jasnozielony, ale oznacza to również, że w przypadku dotknięcia wiersza nie ma żadnego wskaźnika wizualnego:

android:background="#FFDAFF7F"

Aby ponownie włączyć zachowanie wyróżnienia, a także dostosować używany kolor, ustaw atrybut tła na selektor niestandardowy. Selektor zadeklaruje zarówno domyślny kolor tła, jak i kolor wyróżnienia. Plik Resources/Drawable/CustomSelector.xml zawiera następującą deklarację:

<?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>

Aby odwołać się do selektora niestandardowego, zmień atrybut tła w pliku CustomView.axml na:

android:background="@drawable/CustomSelector"

Wybrany wiersz i odpowiedni Toast komunikat wyglądają teraz następująco:

Zaznaczony wiersz w kolorze pomarańczowym z wyskakowaniem komunikatu z wyświetloną nazwą wybranego wiersza

Zapobieganie migotaniu w układach niestandardowych

System Android próbuje poprawić wydajność przewijania ListView przez buforowanie informacji o układzie. Jeśli masz długie listy przewijania danych, należy również ustawić android:cacheColorHint właściwość w ListView deklaracji w definicji AXML działania (na tę samą wartość koloru co tło niestandardowego układu wiersza). Brak uwzględnienia tej wskazówki może spowodować "migotanie", gdy użytkownik przewija listę z niestandardowymi kolorami tła wiersza.