Настройка внешнего вида 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 — группирует строки по категориям, и каждая группа может быть развернута или свернута.

Каждое встроенное представление строк имеет встроенный стиль, связанный с ним. На этих снимках экрана показано, как отображается каждое представление:

Screenshots of TestListItem, SimpleSelectableListItem, SimpleListitem1, and SimpleListItem2

Screenshots of SimpleListItemActivated1, SimpleListItemActivated2, SimpleListItemChecked, and SimpleListItemMultipleChecked

Screenshots of SimpleListItemSingleChoice, TwoLineListItem, ActivityListItem, and SimpleExpandableListItem

Пример файла BuiltInViews/HomeScreenAdapter.csрешении BuiltInViews ) содержит код для создания экранов элементов списка без расширения. Представление задано в методе GetView следующим образом:

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

Затем свойства представления можно задать, ссылаясь на стандартные идентификаторы Text1элементов управления и Text2Icon в разделе 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 — создает списки проверка box-type, где возможны несколько вариантов.

Приведенные выше упоминание аксессуары показаны на следующих экранах в соответствующем порядке:

Screenshots of SimpleListItemChecked, SimpleListItemSingleChoice, and SimpleListItemMultipleChoice with accessories

Чтобы отобразить один из этих аксессуаров, передайте необходимый идентификатор ресурса макета адаптеру, а затем вручную задайте состояние выбора для необходимых строк. В этой строке кода показано, как создать и назначить Adapter один из следующих макетов:

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

Сам по ListView себе поддерживает различные режимы выбора независимо от отображаемой аксессуары. Чтобы избежать путаницы, используйте Single режим выбора с SingleChoice аксессуарами и режимом CheckedMultiple с стилем 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 режиме, необходимо выполнить цикл.CheckedItemPositionsSparseBooleanArray Разреженный массив похож на словарь, содержащий только записи, в которых было изменено значение, поэтому необходимо пройти весь массив, чтобы 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();
}

Полученный экран выглядит следующим образом:

Screenshot of the resulting CustomRowView

Настройка цвета селектора строк

При касании строки ее следует выделить для отзывов пользователей. Если настраиваемое представление указывает как цвет фона, как и 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 сообщение теперь выглядит следующим образом:

A selected row in orange, with Toast message displaying name of selected row

Предотвращение мерцания в пользовательских макетах

Android пытается повысить производительность прокрутки путем кэширования сведений ListView о макете. Если у вас есть длинные списки данных, необходимо также задать android:cacheColorHint свойство ListView в объявлении в определении AXML действия (то же значение цвета, что и фон пользовательского макета строки). Сбой включения этого указания может привести к "мерцание", так как пользователь прокручивает список с настраиваемыми цветами фона строки.