Настройка внешнего вида ListView с помощью Xamarin.Android
Внешний вид ListView определяется макетом отображаемых строк. Чтобы изменить внешний ListView
вид, используйте другой макет строки.
Существует двенадцать встроенных представлений, на которые можно ссылаться с помощью Android.Resource.Layout:
TestListItem — одна строка текста с минимальным форматированием.
SimpleListItem1 — одна строка текста.
SimpleListItem2 — две строки текста.
SimpleSelectableListItem — одна строка текста, поддерживающая выделение одного или нескольких элементов (добавлена на уровне API 11).
SimpleListItemActivated1 — аналогично SimpleListItem1 , но цвет фона указывает, когда выбрана строка (добавлена на уровне API 11).
SimpleListItemActivated2 — аналогично SimpleListItem2, но цвет фона указывает, когда выбрана строка (добавлена на уровне API 11).
SimpleListItemChecked — отображает флажки для указания выделения.
SimpleListItemMultipleChoice — отображает флажки, указывающие выбор нескольких вариантов.
SimpleListItemSingleChoice — отображает переключатели для указания взаимоисключающего выбора.
TwoLineListItem — две строки текста.
ActivityListItem — одна строка текста с изображением.
SimpleExpandableListItem — группирует строки по категориям, и каждая группа может быть развернута или свернута.
Каждое встроенное представление строк имеет встроенный стиль, связанный с ним. На этих снимках экрана показано, как отображается каждое представление:
Пример файла BuiltInViews/HomeScreenAdapter.cs (в решении BuiltInViews ) содержит код для создания экранов элементов списка без расширения. Представление задано в методе GetView
следующим образом:
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
Затем свойства представления можно задать, ссылаясь на стандартные идентификаторы Text1
элементов управления и Text2
Icon
в разделе Android.Resource.Id
(не устанавливайте свойства, которые представление не содержит или исключение будет создано):
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
Пример файла BuiltInExpandableViews/ExpandableScreenAdapter.cs (в решении BuiltInViews ) содержит код для создания экрана SimpleExpandableListItem. Представление группы задано в методе GetGroupView
следующим образом:
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem1, null);
Дочернее представление задано в методе GetChildView
следующим образом:
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem2, null);
Затем можно задать свойства для представления группы и дочернего представления, ссылаясь на стандартные Text1
и Text2
управляющие идентификаторы, как показано выше. Снимок экрана SimpleExpandableListItem (показан выше) содержит пример представления однострочный группы (SimpleExpandableListItem1) и двухстрочный дочерний вид (SimpleExpandableListItem2). Кроме того, представление группы можно настроить для двух строк (SimpleExpandableListItem2), а дочернее представление можно настроить для одной строки (SimpleExpandableListItem1), либо представление группы и дочернее представление могут иметь одинаковое количество строк.
Строки могут иметь аксессуары, добавленные справа от представления, чтобы указать состояние выбора:
SimpleListItemChecked — создает список с одним выделением с проверкой в качестве индикатора.
SimpleListItemSingleChoice — создает списки типов переключателей, где возможен только один выбор.
SimpleListItemMultipleChoice — создает списки типов флажков, где возможны несколько вариантов.
Упомянутые выше аксессуары показаны на следующих экранах в соответствующем порядке:
Чтобы отобразить один из этих аксессуаров, передайте необходимый идентификатор ресурса макета адаптеру, а затем вручную задайте состояние выбора для необходимых строк. В этой строке кода показано, как создать и назначить Adapter
один из следующих макетов:
ListAdapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleListItemChecked, items);
Сам по ListView
себе поддерживает различные режимы выбора независимо от отображаемой аксессуары. Чтобы избежать путаницы, используйте Single
режим выбора с SingleChoice
аксессуарами и режимом Checked
Multiple
с стилем MultipleChoice
. Режим выбора управляется свойством ChoiceMode
объекта ListView
.
Более ранние версии Xamarin.Android реализовали перечисления в виде целочисленных свойств. Последняя версия представила правильные типы перечислений .NET, что упрощает обнаружение потенциальных параметров.
В зависимости от того, какой уровень API вы нацелены, ChoiceMode
является целым числом или перечислением. Пример файла AccessoryViews/HomeScreen.cs содержит закомментированный блок, если вы хотите использовать 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
*/
Вручную задать выбранные элементы с SetItemChecked
помощью метода (его можно вызывать несколько раз для нескольких выборов):
// Set the initially checked row ("Fruits")
lv.SetItemChecked(1, true);
Код также должен обнаруживать отдельные выделения по-разному от нескольких выборов. Чтобы определить, какая строка была выбрана в Single
режиме CheckedItemPosition
, используйте целочисленное свойство:
FindViewById<ListView>(Android.Resource.Id.List).CheckedItemPosition
Чтобы определить, какие строки были выбраны в Multiple
режиме, необходимо выполнить цикл.CheckedItemPositions
SparseBooleanArray
Разреженный массив похож на словарь, содержащий только записи, в которых было изменено значение, поэтому необходимо пройти весь массив, чтобы true
узнать, что было выбрано в списке, как показано в следующем фрагменте кода:
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();
Четыре встроенных представления строк очень просты. Для отображения более сложных макетов (например, списка сообщений электронной почты, твитов или контактных данных) требуется пользовательское представление. Пользовательские представления обычно объявляются как файлы AXML в каталоге Resources/Layout , а затем загружаются с помощью идентификатора ресурса пользовательским адаптером. Представление может содержать любое количество классов отображения (например, TextViews, ImageViews и других элементов управления) с настраиваемыми цветами, шрифтами и макетом.
Этот пример отличается от предыдущих примеров несколькими способами:
Наследует от
Activity
, а неListActivity
. Вы можете настроить строки для любогоListView
элемента управления, однако другие элементы управления также могут быть включены вActivity
макет (например, заголовок, кнопки или другие элементы пользовательского интерфейса). В этом примере добавляется заголовок над иллюстрируемой схемойListView
.Требуется файл макета AXML для экрана; В предыдущих примерах
ListActivity
файл макета не требуется. Этот AXML содержитListView
объявление элемента управления.Требуется файл макета AXML для отрисовки каждой строки. Этот файл AXML содержит элементы управления текстом и изображением с пользовательскими параметрами шрифта и цвета.
При выборе используется необязательный XML-файл пользовательского селектора, чтобы задать внешний вид строки.
Реализация
Adapter
возвращает пользовательский макет изGetView
переопределения.ItemClick
должен быть объявлен по-разному (обработчик событий присоединенListView.ItemClick
вместо переопределенияOnListItemClick
вListActivity
).
Эти изменения подробно описаны ниже, начиная с создания представления действия и пользовательского представления строк, а затем покрытия изменений адаптера и действия для их отрисовки.
Так как HomeScreen
больше не наследуется от ListActivity
него не имеет представления по умолчанию, поэтому для представления HomeScreen необходимо создать файл AXML макета. В этом примере в представлении будет заголовок (с помощью a TextView
) и ListView
для отображения данных. Макет определяется в файле Resources/Layout/HomeScreen.axml , который показан здесь:
<?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>
Преимущество использования Activity
пользовательского макета (вместо a ListActivity
) заключается в том, чтобы добавить дополнительные элементы управления на экран, например заголовок TextView
в этом примере.
Другой файл макета AXML необходим для хранения пользовательского макета для каждой строки, которая будет отображаться в представлении списка. В этом примере строка будет иметь зеленый фон, коричневый текст и выровненное по правому краю изображение. Разметка XML Android для объявления этого макета описана в разделе 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 >
Хотя пользовательский макет строки может содержать множество различных элементов управления, производительность прокрутки может повлиять на сложные проекты и использование изображений (особенно если они должны быть загружены по сети). Дополнительные сведения об устранении проблем с производительностью прокрутки см. в статье Google.
Реализация примера пользовательского адаптера находится в HomeScreenAdapter.cs
. Метод ключа заключается в GetView
том, где он загружает пользовательский AXML с помощью идентификатора Resource.Layout.CustomView
ресурса, а затем задает свойства для каждого элемента управления в представлении перед возвратом. Показан полный класс адаптера:
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;
}
}
HomeScreen
Так как класс теперь наследует отActivity
, ListView
поле объявляется в классе для хранения ссылки на элемент управления, объявленный в AXML:
ListView listView;
Затем класс должен загрузить пользовательский макет действия AXML с помощью SetContentView
метода. Затем он может найти ListView
элемент управления в макете, а затем создать и назначить адаптер и назначить обработчик щелчка. Ниже показан код для метода 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
ItemClick
Наконец, обработчик должен быть определен. В этом случае он просто отображает Toast
сообщение:
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();
}
Полученный экран выглядит следующим образом:
При касании строки ее следует выделить для отзывов пользователей. Если настраиваемое представление указывает как цвет фона, как и CustomView.axml , он также переопределяет выделение выделения. Эта строка кода в CustomView.axml задает для фона светло-зеленый цвет, но это также означает, что визуальный индикатор при касании строки отсутствует:
android:background="#FFDAFF7F"
Чтобы повторно включить поведение выделения, а также настроить используемый цвет, задайте для атрибута фона настраиваемый селектор. Селектор объявляет цвет фона по умолчанию, а также цвет выделения. Файл Resources/Drawable/CustomSelector.xml содержит следующее объявление:
<?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>
Чтобы ссылаться на пользовательский селектор, измените фоновый атрибут в CustomView.axml следующим образом:
android:background="@drawable/CustomSelector"
Выбранная строка и соответствующее Toast
сообщение теперь выглядит следующим образом:
Android пытается повысить производительность прокрутки путем кэширования сведений ListView
о макете. Если у вас есть длинные списки данных, необходимо также задать android:cacheColorHint
свойство ListView
в объявлении в определении AXML действия (то же значение цвета, что и фон пользовательского макета строки). Сбой включения этого указания может привести к "мерцание", так как пользователь прокручивает список с настраиваемыми цветами фона строки.