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

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

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

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

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

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

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

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

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

Котлин

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

Java

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()
        }
    }
}

Java

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()
}

Java

public boolean isShowText() {
   return mShowText;
}

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

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

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

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

Проектирование с учетом доступности

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

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

Для получения дополнительной информации о создании доступных представлений см. раздел «Повышение доступности приложений» .