Přizpůsobení vzhledu ListView pomocí Xamarin.Androidu
Vzhled Objektu ListView je diktován rozložením zobrazených řádků. Pokud chcete změnit vzhled, ListView
použijte jiné rozložení řádku.
Integrovaná zobrazení řádků
Existuje dvanáct předdefinovaných zobrazení, na která lze odkazovat pomocí Android.Resource.Layout:
TestListItem – jeden řádek textu s minimálním formátováním.
SimpleListItem1 – jeden řádek textu.
SimpleListItem2 – dva řádky textu.
SimpleSelectableListItem – jeden řádek textu, který podporuje výběr jedné nebo více položek (přidaný v rozhraní API úrovně 11).
SimpleListItemActivated1 – podobá se SimpleListItem1, ale barva pozadí označuje, kdy je vybrán řádek (přidán v rozhraní API úrovně 11).
SimpleListItemActivated2 – podobá se SimpleListItem2, ale barva pozadí označuje, kdy je vybrán řádek (přidán v rozhraní API úrovně 11).
SimpleListItemChecked – zobrazí značky zaškrtnutí označující výběr.
SimpleListItemMultipleChoice – Zobrazí zaškrtávací políčka označující výběr více voleb.
SimpleListItemSingleChoice – Zobrazí přepínače označující vzájemně se vylučující výběr.
TwoLineListItem – dva řádky textu.
ActivityListItem – jeden řádek textu s obrázkem.
SimpleExpandableListItem – Seskupuje řádky podle kategorií a každá skupina může být rozbalená nebo sbalená.
Každé předdefinované zobrazení řádků má přiřazený předdefinovaný styl. Tyto snímky obrazovky ukazují, jak se každé zobrazení zobrazuje:
Ukázkový soubor BuiltInViews/HomeScreenAdapter.cs (v řešení BuiltInViews ) obsahuje kód, který vytvoří obrazovky položek seznamu, které nelze rozbalit. Zobrazení je nastaveno GetView
v metodě takto:
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
Vlastnosti zobrazení lze potom nastavit odkazem na standardní identifikátory Text1
Text2
ovládacího prvku a Icon
v části Android.Resource.Id
(nenastavujte vlastnosti, které zobrazení neobsahuje nebo dojde k výjimce):
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
Ukázkový soubor BuiltInExpandableViews/ExpandableScreenAdapter.cs (v řešení BuiltInViews ) obsahuje kód pro vytvoření obrazovky SimpleExpandableListItem. Zobrazení skupiny je nastavené v GetGroupView
metodě takto:
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem1, null);
Podřízené zobrazení je nastavené v GetChildView
metodě takto:
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem2, null);
Vlastnosti zobrazení skupiny a podřízeného zobrazení je pak možné nastavit odkazem na standardní Text1
identifikátory a Text2
identifikátory ovládacích prvků, jak je znázorněno výše. Snímek obrazovky SimpleExpandableListItem (viz výše) poskytuje příklad zobrazení skupiny s jedním řádkem (SimpleExpandableListItem1) a dvouřádkového podřízeného zobrazení (SimpleExpandableListItem2). Zobrazení skupiny lze také nakonfigurovat pro dva řádky (SimpleExpandableListItem2) a podřízené zobrazení lze nakonfigurovat pro jeden řádek (SimpleExpandableListItem1), nebo zobrazení skupiny i podřízené zobrazení může mít stejný počet řádků.
Accessories
Řádky můžou mít doplňky přidané napravo od zobrazení, aby bylo možné určit stav výběru:
SimpleListItemChecked – Vytvoří seznam s jedním výběrem s kontrolou jako indikátor.
SimpleListItemSingleChoice – Vytvoří seznamy typů přepínačů, kde je možná jen jedna volba.
SimpleListItemMultipleChoice – Vytvoří seznamy typu zaškrtávacího políčka, kde je možné vybrat více možností.
Výše uvedené příslušenství jsou znázorněny na následujících obrazovkách v příslušném pořadí:
Pokud chcete některý z těchto doplňků zobrazit, předejte adaptéru ID požadovaného prostředku rozložení a potom ručně nastavte stav výběru požadovaných řádků. Tento řádek kódu ukazuje, jak vytvořit a přiřadit Adapter
jedno z těchto rozložení:
ListAdapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleListItemChecked, items);
Samotný ListView
režim výběru podporuje různé režimy výběru bez ohledu na zobrazené příslušenství. Abyste se vyhnuli nejasnostem, použijte Single
režim výběru s příslušenstvím SingleChoice
a Checked
Multiple
režimem se stylem MultipleChoice
. Režim výběru je řízen ChoiceMode
vlastností objektu ListView
.
Zpracování úrovně rozhraní API
Starší verze Xamarin.Android implementovali výčty jako celočíselné vlastnosti. Nejnovější verze zavedla správné typy výčtu .NET, což výrazně usnadňuje zjišťování potenciálních možností.
V závislosti na tom, na jakou úroveň rozhraní API cílíte, je buď celé číslo, ChoiceMode
nebo výčet. Ukázkový soubor AccessoryViews/HomeScreen.cs má blok okomentovaný, pokud chcete cílit na rozhraní API Perník:
// 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
*/
Výběr položek prostřednictvím kódu programu
Ruční nastavení vybraných položek pomocí SetItemChecked
metody (lze ji volat vícekrát pro vícenásobný výběr):
// Set the initially checked row ("Fruits")
lv.SetItemChecked(1, true);
Kód také potřebuje rozpoznat jednotlivé výběry odlišně od několika výběrů. Chcete-li zjistit, který řádek byl vybrán v Single
režimu, použijte CheckedItemPosition
celočíselnou vlastnost:
FindViewById<ListView>(Android.Resource.Id.List).CheckedItemPosition
Chcete-li určit, které řádky byly vybrány v Multiple
režimu, je nutné procházet smyčkou CheckedItemPositions
SparseBooleanArray
. Řídké pole je jako slovník, který obsahuje pouze položky, ve kterých byla hodnota změněna, takže musíte procházet celou matici a zjistit true
, co bylo vybráno v seznamu, jak je znázorněno v následujícím fragmentu kódu:
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();
Vytváření vlastních rozložení řádků
Čtyři integrovaná zobrazení řádků jsou velmi jednoduchá. K zobrazení složitějších rozložení (například seznamu e-mailů nebo tweetů nebo kontaktních údajů) se vyžaduje vlastní zobrazení. Vlastní zobrazení jsou obecně deklarována jako soubory AXML v adresáři Resources/Layout a pak se načtou pomocí id prostředku vlastním adaptérem. Zobrazení může obsahovat libovolný počet tříd zobrazení (například TextViews, ImageViews a další ovládací prvky) s vlastními barvami, písmy a rozložením.
Tento příklad se liší od předchozích příkladů několika způsoby:
Dědí z
Activity
, neListActivity
. Řádky můžete přizpůsobit pro libovolnouListView
položku, ale jiné ovládací prvky mohou být zahrnuty také vActivity
rozložení (například nadpis, tlačítka nebo jiné prvky uživatelského rozhraní). Tento příklad přidá nad obrázek nadpisListView
.Vyžaduje soubor rozložení AXML pro obrazovku; v předchozích příkladech
ListActivity
nevyžaduje soubor rozložení. Tento AXML obsahujeListView
deklaraci ovládacího prvku.K vykreslení každého řádku vyžaduje soubor rozložení AXML. Tento soubor AXML obsahuje ovládací prvky textu a obrázku s vlastním nastavením písma a barvy.
Použije volitelný vlastní soubor XML selektoru k nastavení vzhledu řádku, když je vybrán.
Implementace
Adapter
vrátí vlastní rozložení z přepsáníGetView
.ItemClick
musí být deklarována odlišně (obslužná rutina události je připojenaListView.ItemClick
místo přepsáníOnListItemClick
vListActivity
).
Tyto změny jsou podrobně popsané níže, počínaje vytvořením zobrazení aktivity a vlastním zobrazením řádků a následným pokrytím úprav adaptéru a aktivity, které se mají vykreslit.
Přidání objektu ListView do rozložení aktivity
Protože HomeScreen
už z ListActivity
něj nedědí výchozí zobrazení, musí být pro zobrazení domovské obrazovky vytvořen soubor AXML rozložení. V tomto příkladu bude mít zobrazení nadpis (pomocí TextView
) a ListView
zobrazení dat. Rozložení je definováno v souboru Resources/Layout/HomeScreen.axml , který je zde uvedený:
<?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>
Výhodou použití Activity
vlastního rozložení (místo ListActivity
) je možnost přidat na obrazovku další ovládací prvky, například nadpis TextView
v tomto příkladu.
Vytvoření vlastního rozložení řádku
K zahrnutí vlastního rozložení pro každý řádek, který se zobrazí v zobrazení seznamu, se vyžaduje jiný soubor rozložení AXML. V tomto příkladu bude mít řádek zelené pozadí, hnědý text a obrázek zarovnaný doprava. Kód ANDROID XML, který deklaruje toto rozložení, je popsáno v tématu 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 >
I když vlastní rozložení řádků může obsahovat mnoho různých ovládacích prvků, může být výkon posouvání ovlivněn složitými návrhy a používáním obrázků (zejména pokud je nutné je načíst přes síť). Další informace o řešení problémů s výkonem posouvání najdete v článku Googlu.
Odkazování na vlastní zobrazení řádků
Implementace vlastního adaptéru je v HomeScreenAdapter.cs
příkladu . Metoda klíče je GetView
místo, kde načte vlastní AXML pomocí ID Resource.Layout.CustomView
prostředku a potom nastaví vlastnosti na každém ovládacím prvku v zobrazení před vrácením. Zobrazí se úplná třída adaptéru:
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;
}
}
Odkazování na vlastní objekt ListView v aktivitě
Vzhledem k tomu, že HomeScreen
třída nyní dědí z Activity
, ListView
pole je deklarováno ve třídě pro uložení odkazu na ovládací prvek deklarovaný v AXML:
ListView listView;
Třída pak musí pomocí metody načíst vlastní rozložení AXML SetContentView
aktivity. Pak může najít ListView
ovládací prvek v rozložení a pak vytvoří a přiřadí adaptér a přiřadí obslužnou rutinu kliknutí. Zde je uveden kód pro metodu OnCreate:
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
Nakonec musí být definována ItemClick
obslužná rutina. V tomto případě pouze zobrazí Toast
zprávu:
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();
}
Výsledná obrazovka vypadá takto:
Přizpůsobení barvy selektoru řádků
Když se dotknete řádku, měl by se zvýraznit pro zpětnou vazbu uživatelů. Když vlastní zobrazení určuje barvu pozadí jako CustomView.axml , přepíše také zvýraznění výběru. Tento řádek kódu v CustomView.axml nastaví pozadí na světle zelenou, ale také to znamená, že při dotyku řádku není žádný vizuální indikátor:
android:background="#FFDAFF7F"
Pokud chcete chování zvýraznění znovu povolit a také přizpůsobit použitou barvu, nastavte atribut pozadí na vlastní selektor. Selektor deklaruje výchozí barvu pozadí i barvu zvýraznění. Soubor Resources/Drawable/CustomSelector.xml obsahuje následující deklaraci:
<?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>
Pokud chcete odkazovat na vlastní selektor, změňte atribut pozadí v CustomView.axml na:
android:background="@drawable/CustomSelector"
Vybraný řádek a odpovídající Toast
zpráva teď vypadají takto:
Zabránění blikání ve vlastních rozloženích
Android se pokouší zlepšit výkon ListView
posouvání informacemi rozložení do mezipaměti. Pokud máte dlouhé posouvání seznamů dat, měli byste také nastavit android:cacheColorHint
vlastnost deklarace ListView
v definici AXML aktivity (na stejnou barevnou hodnotu jako pozadí vlastního rozložení řádku). Pokud tuto nápovědu nezahrnete, může dojít k "blikání", protože uživatel prochází seznam s vlastními barvami pozadí řádku.