Настройка внешнего вида 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
.
Обработка уровня API
Более ранние версии 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
).
Эти изменения подробно описаны ниже, начиная с создания представления действия и пользовательского представления строк, а затем покрытия изменений адаптера и действия для их отрисовки.
Добавление ListView в макет действия
Так как 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;
}
}
Ссылка на custom ListView в действии
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 действия (то же значение цвета, что и фон пользовательского макета строки). Сбой включения этого указания может привести к "мерцание", так как пользователь прокручивает список с настраиваемыми цветами фона строки.