Создать класс представления

Попробуйте способ создания
Jetpack Compose — рекомендуемый набор инструментов пользовательского интерфейса для Android. Узнайте, как работать с макетами в Compose.

Хорошо спроектированное пользовательское представление похоже на любой другой хорошо спроектированный класс. Он инкапсулирует определенный набор функций с простым интерфейсом, эффективно использует процессор и память и т. д. Помимо того, что пользовательское представление является хорошо спроектированным классом, оно должно выполнять следующее:

  • Соответствует стандартам Android.
  • Предоставляйте настраиваемые стилизованные атрибуты, которые работают с макетами Android XML.
  • Отправлять события доступности.
  • Быть совместимым с несколькими платформами Android.

Платформа Android предоставляет набор базовых классов и тегов XML, которые помогут вам создать представление, отвечающее всем этим требованиям. В этом уроке обсуждается, как использовать платформу Android для создания основных функций класса представления.

Дополнительную информацию можно найти в разделе Компоненты пользовательского представления .

Подкласс представления

Все классы представлений, определенные в платформе Android, расширяют View . Ваше пользовательское представление также может напрямую расширять View , или вы можете сэкономить время, расширив один из существующих подклассов представления, например Button .

Чтобы позволить Android Studio взаимодействовать с вашим представлением, вы должны как минимум предоставить конструктор, который принимает объект Context и AttributeSet в качестве параметров. Этот конструктор позволяет редактору макета создавать и редактировать экземпляр вашего представления.

Котлин

class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)

Ява

class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

Определите пользовательские атрибуты

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

  • Определите пользовательские атрибуты для вашего представления в элементе ресурса <declare-styleable> .
  • Укажите значения атрибутов в макете XML.
  • Получить значения атрибутов во время выполнения.
  • Примените полученные значения атрибутов к вашему представлению.

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

Чтобы определить пользовательские атрибуты, добавьте в свой проект ресурсы <declare-styleable> . Обычно эти ресурсы помещаются в файл res/values/attrs.xml . Вот пример файла attrs.xml :

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>

Этот код объявляет два пользовательских атрибута, showText и labelPosition , которые принадлежат стилизуемой сущности с именем PieChart . Имя стилизуемой сущности по соглашению совпадает с именем класса, определяющего пользовательское представление. Хотя следовать этому соглашению не обязательно, многие популярные редакторы кода используют это соглашение об именах для обеспечения завершения операторов.

Определив пользовательские атрибуты, вы можете использовать их в XML-файлах макета так же, как встроенные атрибуты. Единственное отличие состоит в том, что ваши пользовательские атрибуты принадлежат другому пространству имен. Вместо того, чтобы принадлежать к пространству имен http://schemas.android.com/apk/res/android , они принадлежат http://schemas.android.com/apk/res/[your package name] . Например, вот как использовать атрибуты, определенные для PieChart :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res-auto">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

Чтобы избежать повторения длинного URI пространства имен, в примере используется директива xmlns . Эта директива назначает custom псевдоним пространству имен http://schemas.android.com/apk/res/com.example.customviews . Вы можете выбрать любой псевдоним для своего пространства имен.

Обратите внимание на имя тега XML, который добавляет пользовательское представление в макет. Это полное имя класса пользовательского представления. Если ваш класс представления является внутренним классом, укажите в нем имя внешнего класса представления. Например, класс PieChart имеет внутренний класс PieView . Чтобы использовать пользовательские атрибуты из этого класса, используйте тег com.example.customviews.charting.PieChart$PieView .

Применить пользовательские атрибуты

Когда представление создается из макета XML, все атрибуты в теге XML считываются из пакета ресурсов и передаются в конструктор представления как AttributeSet . Хотя можно напрямую считывать значения из AttributeSet , это имеет некоторые недостатки:

  • Ссылки на ресурсы в значениях атрибутов не разрешаются.
  • Стили не применяются.

Вместо этого передайте AttributeSet в obtainStyledAttributes() . Этот метод передает обратно массив значений TypedArray , которые уже разыменованы и оформлены.

Компилятор ресурсов Android проделал большую работу, чтобы упростить вызов метода obtainStyledAttributes() . Для каждого ресурса <declare-styleable> в каталоге res/ сгенерированный R.java определяет как массив идентификаторов атрибутов, так и набор констант, которые определяют индекс для каждого атрибута в массиве. Вы используете предопределенные константы для чтения атрибутов из TypedArray . Вот как класс PieChart считывает свои атрибуты:

Котлин

init {
    context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.PieChart,
            0, 0).apply {

        try {
            mShowText = getBoolean(R.styleable.PieChart_showText, false)
            textPos = getInteger(R.styleable.PieChart_labelPosition, 0)
        } finally {
            recycle()
        }
    }
}

Ява

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       textPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}

Обратите внимание, что объекты TypedArray являются общим ресурсом и должны быть переработаны после использования.

Добавить свойства и события

Атрибуты — мощный способ управления поведением и внешним видом представлений, но их можно прочитать только при инициализации представления. Чтобы обеспечить динамическое поведение, предоставьте пару методов получения и установки свойств для каждого настраиваемого атрибута. В следующем фрагменте показано, как PieChart предоставляет свойство showText :

Котлин

fun isShowText(): Boolean {
    return mShowText
}

fun setShowText(showText: Boolean) {
    mShowText = showText
    invalidate()
    requestLayout()
}

Ява

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

Обратите внимание, что setShowText вызывает invalidate() и requestLayout() . Эти вызовы имеют решающее значение для обеспечения надежного поведения представления. Вам необходимо сделать представление недействительным после любого изменения его свойств, которое может изменить его внешний вид, чтобы система знала, что его необходимо перерисовать. Аналогично, вам необходимо запросить новый макет, если свойство изменяется таким образом, что может повлиять на размер или форму представления. Если забыть об этих вызовах методов, это может привести к трудно обнаруживаемым ошибкам.

Пользовательские представления также должны поддерживать прослушиватели событий для передачи важных событий. Например, PieChart предоставляет пользовательское событие OnCurrentItemChanged , чтобы уведомить слушателей о том, что пользователь повернул круговую диаграмму, чтобы сосредоточиться на новом фрагменте круговой диаграммы.

Легко забыть предоставить доступ к свойствам и событиям, особенно если вы единственный пользователь пользовательского представления. Уделяя время тщательному определению интерфейса вашего представления, вы снижаете будущие затраты на обслуживание. Хорошее правило, которому следует следовать, — всегда раскрывать любое свойство, которое влияет на видимый внешний вид или поведение вашего пользовательского представления.

Дизайн для доступности

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

  • Пометьте поля ввода, используя атрибут android:contentDescription .
  • Отправляйте события доступности, вызывая sendAccessibilityEvent() когда это необходимо.
  • Поддержка альтернативных контроллеров, таких как D-pad или трекбол.

Дополнительные сведения о создании доступных представлений см. в разделе «Как сделать приложения более доступными» .