Урок 10. Android Data Binding. Binding Adapters

Binding Adapters, создание пользовательских атрибутов

На прошлом уроке мы изучали обработку пользовательских событий ввода и работу с наблюдаемыми данными (observable data), при изменении которых будет меняться их представление.

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

Когда вы связываете строку (или наблюдаемую строку) с android:textатрибутом, становится совершенно очевидно, что произойдет, но каким образом это происходит?

Благодаря библиотеке привязки данных почти все вызовы пользовательского интерфейса выполняются в статических методах, называемых адаптерами привязки.

Библиотека предоставляет огромное количество связывающих адаптеров. Посмотрите их здесь . Вот пример для атрибута android:text:

  @BindingAdapter("android:text")
    public static void setText(TextView view, CharSequence text) {
        // Some checks removed for clarity

        view.setText(text);
    }

Или android:background:

@BindingAdapter("android:background")
    public static void setBackground(View view, Drawable drawable) {
        if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
            view.setBackground(drawable);
        } else {
            view.setBackgroundDrawable(drawable);
        }
    }

В привязке данных нет магии. Все решается во время компиляции и доступно для чтения в сгенерированном коде.

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

Мы хотим, чтобы выполнялись следующие условия:

  • Индикатор был невидимым, если нет лайков
  • Заполнялся после 5 лайков
  • Изменял цвет, если заполненУрок 10. Android Data Binding. Binding Adapters

Давайте создадим собственные адаптеры привязки для этого.

Создайте файл BindingAdapters.kt. Неважно, где вы создадите адаптеры, библиотека их найдет. В Kotlin статические методы можно создавать, добавляя функции на верхний уровень Котлин-файла или как функции расширения класса.

Создайте внутри адаптер связывания для первого условияhideIfZero:

  @BindingAdapter("app:hideIfZero")
    fun hideIfZero(view: View, number: Int) {
        view.visibility = if (number == 0) View.GONE else View.VISIBLE
    }

Это обязательный адаптер, который:

  1. относится к атрибуту app:hideIfZero.
  2. может применяться к каждому представлению (поскольку первый параметр является представлением; вы можете ограничить его определенными классами, изменив этот тип)
  3. принимает Integer , который возвращает выражение макета.
  4. Выполняет View GONE, если число равно нулю. В противном случае VISIBLE .

В макете разметки найдите индикатор выполнения и добавьте атрибут hideIfZero:

  <ProgressBar
            android:id="@+id/progressBar"
            app:hideIfZero="@{viewmodel.likes}"
...

Запустите приложение, и вы увидите, что индикатор выполнения отображается при первом нажатии кнопки. Однако нам все еще нужно изменить его значение и цвет:

Урок 10. Android Data Binding. Binding Adapters

Binding Adapters с несколькими параметрами

Для значения прогресса мы будем использовать адаптер привязки, который принимает максимальное значение и количество лайков. Откройте файл BindingAdaptersи добавьте это:

@BindingAdapter(value = ["app:progressScaled", "android:max"], requireAll = true)
fun setProgress(progressBar: ProgressBar, likes: Int, max: Int) {
    progressBar.progress = (likes * max / 5).coerceAtMost(max)
}

Этот адаптер привязки не используется, если какие-либо атрибуты отсутствуют. Это определяется во время компиляции. Теперь метод принимает 3 параметра (представление, к которому он применяется + количество атрибутов, определенных в аннотации).

Параметр requireAll определяет , когда используется связывающий адаптер:

  • Если trueвсе элементы должны присутствовать в определении XML.
  • Если falseотсутствующие атрибуты будут иметь значение null, false, если логическое значение, или 0, если примитивы.

Теперь добавьте атрибуты в XML:

  <ProgressBar
                android:id="@+id/progressBar"
                app:hideIfZero="@{viewmodel.likes}"
                app:progressScaled="@{viewmodel.likes}"
                android:max="@{100}"
...

Мы привязываем атрибут progressScaled к количеству лайков и просто передаем целое число в атрибут max. Если вы не добавите формат @{}, привязка данных не сможет найти правильный адаптер привязки.

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

Практика создания Binding Adapters

Практика помогает закрепить материал. В качестве домашнего задания создайте:

  1. Адаптер связывания, который окрашивает цвет индикатора выполнения в зависимости от значения лайков и добавляет соответствующий атрибут
  2. Адаптер связывания, который показывает различный значок в зависимости от популярности:
  • ic_person_black_96dp в черном цвете
  • ic_whatshot_black_96dp в светло-розовом цвете
  • ic_whatshot_black_96dp в насыщенном розовом цвете

Урок 10. Android Data Binding. Binding Adapters

На этом наш урок подошел к концу.
Исходный код проекта можно скачать здесь.

До встречи на следующем уроке, всем добра.

Урок 11. Принципы навигации внутри и между андроид-приложениями

Коментарі: 4
  1. genbachae
    genbachae

    Виталий, ДЗ выполнил но значок не меняется, подскажите пожалуйста в чём ошибка? – https://drive.google.com/open?id=125uOUhihvcU6_WR8NVlo47jBTuPeeboa

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

    1. Виталий Непочатов
      admin (автор)

      В исходном проекте работает? Сверьте ваш код с исходниками. Я бы сделал то же самое.

  2. genbachae
    genbachae

    Виталий, у вас ошибка в тексте урока:
    ic_whatshot_black_96dp в светло-розовом цвете
    ic_whatshot_black_96dp в насыщенном розовом цвете

    два раза повторяется одно и тоже имя файла: “ic_whatshot_black_96dp”.
    А в самом проекте лежит всего два файла:
    ic_person_black_96dp
    ic_whatshot_black_96dp
    третьего файла нет!

    1. Виталий Непочатов
      admin (автор)

      Это не ошибка, второй файл должен быть закрашен разными цветами

Додати коментар

Цей сайт використовує Akismet для зменшення спаму. Дізнайтеся, як обробляються ваші дані коментарів.