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:
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 Text1
kontrolek 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:
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 nieListActivity
. Można dostosować wiersze dla dowolnegoListView
elementu , jednak inne kontrolki można również uwzględnić wActivity
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ę kontrolkiListView
.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 zGetView
przesłonięcia.ItemClick
program obsługi zdarzeń musi być zadeklarowany inaczej (program obsługi zdarzeń jest dołączony doListView.ItemClick
elementu , a nie do zastępowaniaOnListItemClick
w plikuListActivity
).
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.CustomView
zasobu , 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 Activity
klasy , 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:
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:
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.