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

Вступление

Как разработчики, мы ежедневно проектируем различные виды пользовательского интерфейса, используя XML, но изучение пользовательских представлений - действительно простая и замечательная вещь. Используйте преимущества создания пользовательских представлений и избегайте повторения шаблонного кода.

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

Лучше всего узнать жизненный цикл представления, прежде чем углубляться в настраиваемые представления.

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

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

  1. Производительность: если у вас много представлений в макете и вы хотите их оптимизировать, нарисовав один настраиваемый вид, чтобы сделать его светлее
  2. Сложная иерархия представлений, с которой сложно работать и поддерживать
  3. Полный настраиваемый вид, требующий рисования вручную

Базовый обзор

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

  1. Создайте класс и расширьте класс или подкласс базового представления.
  2. Предоставьте конструкторы для получения атрибутов из XML.
  3. Переопределите некоторые методы суперкласса. Такие методы, как onDraw (), onMeasure () и т. Д., В соответствии с нашими требованиями.
  4. После завершения ваш новый класс расширения можно использовать вместо представления, на котором он был основан.

Пример

В одном из моих проектов у меня было требование создать круговой TextView для отображения количества уведомлений. Здесь нам нужно создать подкласс TextView.

Шаг 1. Создайте класс с именем CircularTextView.

Шаг 2. Расширьте класс виджета TextView. Теперь IDE выдает ошибку в TextView, говоря, что этот тип имеет конструктор и должен быть инициализирован здесь.

Шаг 3. Добавьте конструкторы в класс.

Это можно сделать двумя способами

Один из способов - добавить в класс конструкторы, как показано ниже.

Другой способ - добавить @JvmOverloads к вызову конструктора, как показано ниже.

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

Просмотр (контекстный контекст)

Простой конструктор для использования при динамическом создании представления из кода. Здесь контекст параметра - это контекст, в котором выполняется представление, через которое оно может получить доступ к текущей теме, ресурсам и т. Д.

Просмотр (контекстный контекст, атрибуты @Nullable AttributeSet)

Конструктор, вызываемый при расширении представления из XML. Это вызывается, когда представление создается из файла XML, предоставляя атрибуты, указанные в файле XML. В этой версии используется стиль по умолчанию 0, поэтому применяются только значения атрибутов в теме контекста и в заданном наборе атрибутов.

Шаг 4: Самый важный шаг в рисовании настраиваемого представления - переопределить onDraw () и реализацию вашей логики внутри него.

OnDraw (canvas: Canvas?) Имеет параметр Canvas, с помощью которого компонент представления может рисовать себя. Чтобы рисовать на холсте, необходимо создать объект Paint.

В основном рисунок разделен на две области

  • Что рисовать, обрабатывает Canvas
  • Как рисовать, занимается Paint.

Canvas предоставляет метод рисования линии, а Paint предоставляет методы для определения цвета этой линии. В нашем примере CircularTextView Canvas предоставляет метод рисования круга, в то время как объект Paint заполняет цвет. Мы можем просто сказать, что Canvas определяет формы, которые вы можете рисовать на экране, в то время как Paint определяет свойства, такие как цвет, стиль, шрифт и т. Д., Каждой формы, которую вы рисуете.

Давайте перейдем к кодированию. Мы создаем объект Paint и назначаем ему некоторые свойства, а затем рисуем фигуру на холсте, используя этот объект Paint. onDraw () будет просто выглядеть следующим образом

IDE показывает предупреждение, чтобы избежать выделения объектов во время операций рисования / макета. Потому что метод onDraw () вызывается много раз при рендеринге представления, которое каждый раз создает ненужные объекты. Поэтому, чтобы избежать создания ненужного объекта, нам нужно переместить эту часть из onDraw (), как показано ниже.

Выполняя рисование, всегда помните о повторном использовании объектов вместо создания новых. Не полагайтесь на свою среду IDE, которая укажет на потенциальную проблему, а сделайте это самостоятельно, потому что среда IDE не сможет ее увидеть, если вы создаете объекты внутри методов, вызываемых из onDraw ().

Шаг 5: Теперь мы закончили рисовать, давайте расширим этот класс представления в XML.

Добавьте этот XML-макет в свою деятельность и запустите приложение. Следующее будет выходом.

Это здорово, правда? Теперь давайте сделаем это динамическое свойство circlePaint color, назначенное из Activity вместе с некоторой обводкой. Для этого нам нужно создать несколько методов установки в нашем классе CircularTextView, чтобы мы могли вызывать эти методы и устанавливать свойства динамически.

Для начала настроим цвет краски. Для этого мы создаем метод установки, как показано ниже.

fun setSolidColor(color: String) {
    solidColor = Color.parseColor(color)
    circlePaint?.color = solidColor
}

Теперь из Activity мы можем динамически устанавливать цвет, вызывая этот метод.

circularTextView.setSolidColor("#FF0000")

Круто, правда? Теперь давайте добавим обводку к кругу. Для штриха требуются два параметра: ширина штриха и цвет штриха. Для цвета обводки нам нужно создать объект Paint так же, как мы сделали для круга выше. Для ширины штриха мы создаем переменную, устанавливаем для нее это значение и используем это значение в onDraw (). Полный код будет выглядеть следующим образом.

И из активности динамически установите атрибуты, чтобы настроить его.

Теперь запустим приложение, задав разные цвета.

Теперь у нас есть представление о том, как устанавливать свойства динамически из Activity, но возникнет вопрос, как устанавливать атрибуты из XML. Давайте продолжим изучение.

Для этого мы сначала создаем новый файл в папке значений с именем attrs.xml. Этот файл содержит все атрибуты для различных настраиваемых представлений. В приведенном ниже примере у нас есть представление под названием CircularTextView с атрибутом ct_circle_fill_color, который принимает цветовой ввод. Точно так же мы можем добавить и другие атрибуты.

Затем, во-вторых, нам нужно прочитать эти свойства в нашем классе Custom View. Из блока инициализации мы читаем набор атрибутов, как показано ниже.

val typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CircularTextView)
circlePaint?.color = typedArray.getColor(R.styleable.CircularTextView_ct_circle_fill_color,Color.BLUE)
typedArray.recycle()

Теперь просто перейдите в XML и установите для свойства любой желаемый цвет и запустите приложение. Вы увидите требуемый результат.

app:ct_circle_fill_color="@color/green"

В моем случае выход был.

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

Просмотр обновлений

Мы закончили с настройкой представления, если произошло изменение свойства или вы хотите обновить настраиваемое представление. В основном есть два метода

недействительный ()

invalidate () - это метод, который настаивает на принудительном повторном рисовании определенного представления, в котором мы хотим отобразить изменения. Проще говоря, мы можем сказать, что invalidate () нужно вызывать при изменении внешнего вида представления.

requestLayout ()

В какой-то момент в представлении происходит изменение состояния, затем requestLayout () является сигналом для системы представления о том, что ей необходимо пересчитать этапы измерения и макета представлений (измерение → макет → рисование). Проще говоря, мы можем сказать, что requestLayout () необходимо вызывать, когда произошло изменение границ представления.

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

Спасибо за чтение.