Kotlin Android Fundamentals 10.3: Дизайн для всех

Эта практическая работа входит в курс «Основы Android Kotlin». Вы получите максимальную пользу от этого курса, если будете выполнять практические работы последовательно. Все практические работы курса перечислены на целевой странице практической работы «Основы Android Kotlin» .

Введение

Сделать приложение доступным для максимального числа пользователей — это разумный подход, независимо от того, разрабатываете ли вы его для удовольствия или в коммерческих целях. Достижение этого требует множества факторов.

  • Поддержка языков с написанием справа налево (RTL). Европейские и многие другие языки читаются слева направо, и приложения, разработанные для этих языков, обычно разрабатываются с учётом особенностей этих языков. Многие другие языки с большим количеством носителей, например, арабский, читаются справа налево. Настройте своё приложение на работу с языками с написанием справа налево (RTL), чтобы расширить потенциальную аудиторию.
  • Сканирование доступности. Гадать о том, как кто-то другой воспримет ваше приложение, — это вариант, который таит в себе подводные камни. Приложение «Сканер доступности» избавляет от необходимости гадать и анализирует ваше приложение, выявляя возможности улучшения его доступности.
  • Дизайн для TalkBack с описаниями контента. Нарушения зрения встречаются чаще, чем можно подумать, и многие пользователи, не только слепые, используют программы чтения с экрана. Описания контента — это фразы, которые программа чтения с экрана произносит, когда пользователь взаимодействует с элементом экрана.
  • Поддержка ночного режима . Для многих пользователей с нарушениями зрения изменение цветов экрана улучшает контрастность и облегчает работу с вашим приложением. Поддержка ночного режима в Android реализована просто, и вам следует всегда поддерживать ночной режим, чтобы предоставить пользователям простую альтернативу цветам экрана по умолчанию.

В этой лабораторной работе вы изучите каждый из этих вариантов и добавите его поддержку в приложение GDG Finder.

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

Что вам уже следует знать

Вам должно быть знакомо:

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

Чему вы научитесь

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

Что ты будешь делать?

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

Стартовое приложение GDG-finder создано с учетом всего, что вы уже изучили в этом курсе.

Приложение использует ConstraintLayout для создания трёх экранов. Два из них — это просто файлы макетов, которые вы будете использовать для изучения цветов и текста на Android.

Третий экран — поисковая система GDG. GDG (группы разработчиков Google) — это сообщества разработчиков, специализирующиеся на технологиях Google, включая Android. GDG по всему миру проводят встречи, конференции, учебные семинары и другие мероприятия.

При разработке этого приложения вы работаете с реальным списком GDG. Экран поиска использует местоположение устройства для сортировки GDG по расстоянию.

Если вам повезёт и в вашем регионе есть GDG, вы можете зайти на сайт и зарегистрироваться на их мероприятия! Мероприятия GDG — отличный способ познакомиться с другими разработчиками Android и изучить передовой опыт отрасли, который не вошел в этот курс.

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

Основное различие между языками с письмом слева направо (LTR) и справа налево (RTL) заключается в направлении отображаемого содержимого. Изменение направления пользовательского интерфейса с LTR на RTL (или наоборот) часто называется зеркальным отображением. Зеркальное отображение затрагивает большую часть экрана, включая текст, значки текстовых полей, макеты и значки с направлениями (например, стрелки). Другие элементы не зеркалируются, например, числа (часы, номера телефонов), значки без направления (режим полета, Wi-Fi), элементы управления воспроизведением и большинство диаграмм и графиков.

Языки с направлением письма справа налево используют более миллиарда человек по всему миру. Разработчики Android работают по всему миру, поэтому приложение GDG Finder должно поддерживать языки с направлением письма справа налево.

Шаг 1: Добавьте поддержку RTL

На этом этапе вы настроите приложение GDG Finder для работы с языками с письмом справа налево.

  1. Загрузите и запустите приложение GDGFinderMaterial , которое является стартовым приложением для этой лабораторной работы, или продолжите с финального кода предыдущей лабораторной работы.
  2. Откройте манифест Android.
  3. В разделе <application> добавьте следующий код, чтобы указать, что приложение поддерживает RTL.
<application
        ...
        android:supportsRtl="true">
  1. Откройте activity_main.xml на вкладке «Дизайн» .
  2. В раскрывающемся меню «Язык для предварительного просмотра» выберите «Предварительный просмотр справа налево» . (Если вы не видите это меню, разверните панель или закройте панель « Атрибуты» , чтобы открыть её.)

  1. В окне предварительного просмотра обратите внимание, что заголовок «GDG Finder» сместился вправо, а остальная часть экрана осталась практически прежней. В целом, этот экран приемлем. Но выравнивание в текстовом представлении теперь неправильное, поскольку он выровнен по левому краю, а не по правому.

  1. Чтобы это заработало на вашем устройстве, в настройках устройства или эмулятора, в параметрах разработчика , выберите Принудительная раскладка RTL . (Если вам нужно включить параметры разработчика , найдите номер сборки и щелкайте по нему, пока не появится уведомление о том, что вы являетесь разработчиком. Это зависит от устройства и версии системы Android.)

  1. Запустите приложение и убедитесь, что главный экран устройства выглядит так же, как в предварительном просмотре . Обратите внимание, что FAB теперь переключился влево, а меню «Гамбургер» — вправо!
  2. В приложении откройте панель навигации и перейдите на экран поиска . Как показано ниже, значки по-прежнему находятся слева, а текст не виден. Оказывается, текст находится за пределами экрана, слева от значка. Это связано с тем, что код использует ссылки на левый/правый экран в свойствах представления и ограничениях макета.

Шаг 2: Используйте начало и конец вместо левого и правого.

Положения «left» и «right» на экране (если смотреть на него) не меняются, даже если меняется направление текста. Например, layout_constraintLeft_toLeftOf всегда ограничивает левую сторону элемента левой стороной экрана. В вашем приложении текст в языках с письмом справа налево находится за пределами экрана, как показано на снимке экрана выше.

Чтобы исправить это, вместо «слева» и «справа» используйте термины Start и End ». Этот термин задаёт начало и конец текста в соответствии с направлением текста на текущем языке, чтобы поля и макеты располагались в правильных областях экрана.

  1. Open list_item.xml .
  2. Замените все ссылки на Left и Right ссылками на Start и End .
app:layout_constraintStart_toStartOf="parent"

app:layout_constraintStart_toEndOf="@+id/gdg_image"
app:layout_constraintEnd_toEndOf="parent"
  1. Замените layout_marginLeft элемента ImageView на свойство layout_marginStart . Это переместит поле в нужное положение, чтобы отодвинуть значок от края экрана.
<ImageView
android:layout_marginStart="
?
  1. Откройте файл fragment_gdg_list.xml . Проверьте список GDG на панели предварительного просмотра . Обратите внимание, что значок по-прежнему указывает в неправильном направлении, поскольку он зеркально отражён (если значок не зеркально отражён, убедитесь, что вы всё ещё смотрите на предварительный просмотр справа налево). Согласно принципам Material Design, значки не должны зеркально отражаться.
  2. Откройте res/drawable/ic_gdg.xml .
  3. В первой строке XML-кода найдите и удалите android:autoMirrored="true" , чтобы отключить зеркалирование.
  4. Проверьте предварительный просмотр или запустите приложение ещё раз и откройте экран поиска GDG. Теперь макет должен быть исправлен!

Шаг 3: позвольте Android Studio сделать всю работу за вас

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

  1. В list_item.xml , в TextView , измените layout_marginStart обратно на layout_marginLeft , чтобы сканеру было что искать.
<TextView
android:layout_marginLeft="@dimen/spacing_normal"
  1. В Android Studio выберите «Рефакторинг» > «Добавить поддержку RTL, где это возможно» и установите флажки для обновления манифеста и файлов макета, чтобы использовать начальные и конечные свойства.

  1. На панели предварительного просмотра рефакторинга найдите папку приложения и разверните ее, пока не откроются все подробности.
  2. В папке приложения обратите внимание, что layout_marginLeft , который вы только что изменили, указан как код для рефакторинга.

  1. Обратите внимание, что в предварительном просмотре также отображаются системные файлы и файлы библиотек. Щёлкните правой кнопкой мыши по layout и l ayout-watch-v20 , а также по любым другим папкам, не входящим в состав app , и выберите «Исключить» в контекстном меню.

  1. Продолжайте и выполните рефакторинг прямо сейчас. (Если появится всплывающее окно с информацией о системных файлах, убедитесь, что вы исключили все папки, которые не являются частью кода вашего приложения .)
  1. Обратите внимание, что layout_marginLeft снова изменился на layout_marginStart .

Шаг 3: Поиск локалей в папках

На этом этапе вы только что изменили язык по умолчанию, используемый в приложении. Для производственного приложения вам потребуется отправить файл strings.xml переводчику для перевода на новый язык. Для этой лабораторной работы приложение предоставляет файл strings.xml на испанском языке (мы использовали Google Translate для создания переводов, поэтому они неидеальны).

  1. В Android Studio переключите вид проекта на Файлы проекта.
  2. Разверните папку res и обратите внимание на папки res/values и res/values-es . «es» в имени папки — это код испанского языка . Папки values-«language code» содержат значения для каждого поддерживаемого языка. Папка values без расширения содержит ресурсы по умолчанию, которые применяются в остальных случаях.

  1. В values-es откройте strings.xml и обратите внимание, что все строки на испанском языке.
  2. В Android Studio откройте activity_main.xml на вкладке «Дизайн» .
  3. В раскрывающемся списке «Язык предварительного просмотра» выберите «Испанский» . Теперь текст будет на испанском языке.

  1. [Необязательно] Если вы владеете языком с письмом справа налево, создайте папку values и файл strings.xml на этом языке и проверьте, как они выглядят на вашем устройстве.
  2. [Необязательно] Измените языковые настройки на устройстве и запустите приложение. Не меняйте язык устройства на тот, который вы не знаете, так как это может затруднить отмену!

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

Приложение Accessibility Scanner — ваш лучший помощник в обеспечении доступности вашего приложения. Оно сканирует ваше приложение на целевом устройстве и предлагает улучшения, такие как увеличение области касания, повышение контрастности и добавление описаний к изображениям, чтобы сделать ваше приложение более доступным. Accessibility Scanner разработан Google, и вы можете установить его из Play Маркета.

Шаг 1: Установите и запустите сканер доступности

  1. Откройте Play Store и при необходимости войдите в систему. Это можно сделать как на физическом устройстве, так и на эмуляторе. В этой лабораторной работе используется эмулятор.
  1. В Play Маркете найдите Accessibility Scanner от Google LLC . Убедитесь, что вы скачали правильное приложение от Google, так как для любого сканирования требуется множество разрешений!

  1. Установите сканер на эмулятор.
  2. После установки нажмите «Открыть» .
  3. Нажмите «Начать» .
  4. Нажмите «ОК» , чтобы начать настройку сканера доступности в настройках.

  1. Нажмите «Сканер доступности», чтобы перейти к настройкам специальных возможностей устройства.

  1. Нажмите «Использовать службу» , чтобы включить ее.

  1. Следуйте инструкциям на экране и предоставьте все разрешения.
  2. Затем нажмите «ОК» (Понятно) и вернитесь на главный экран. Где-то на экране вы можете увидеть синюю кнопку с галочкой. Нажатие этой кнопки запускает тестирование приложения на переднем плане. Вы можете перетащить кнопку, чтобы изменить её положение. Эта кнопка отображается поверх всех приложений, поэтому вы можете запустить тестирование в любой момент.

  1. Откройте или запустите ваше приложение.
  2. Нажмите синюю кнопку и примите дополнительные предупреждения безопасности и разрешения.

При первом нажатии на значок «Сканер доступности» приложение запрашивает разрешение на отображение всего содержимого на экране. Это разрешение кажется очень пугающим, и так оно и есть.

Почти никогда не следует предоставлять такое разрешение, потому что оно позволяет приложениям читать вашу электронную почту или даже получать данные вашего банковского счёта! Однако для работы сканера доступности ему необходимо проверять ваше приложение так же, как это делает пользователь, — именно поэтому ему и нужно это разрешение.

  1. Нажмите синюю кнопку и дождитесь завершения анализа. Вы увидите что-то похожее на скриншот ниже: заголовок и FAB выделены красным. Это означает два предложения по улучшению доступности на этом экране.

  1. Щелкните по рамке вокруг GDG Finder. Откроется панель с дополнительной информацией, как показано ниже, указывающей на проблемы с контрастностью изображения.
  2. Разверните информацию о контрастности изображения , и инструмент предложит варианты решения проблемы.
  3. Нажмите на стрелки справа, чтобы получить информацию о следующем элементе.

  1. В вашем приложении перейдите на экран «Подать заявку на GDG» и отсканируйте его с помощью приложения «Сканер доступности». Оно выдаст довольно много предложений, как показано ниже слева. 12, если быть точным. Справедливости ради, некоторые из них дублируют похожие пункты.
  2. Нажмите «стек» Нажмите на значок на нижней панели инструментов, чтобы получить список всех предложений, как показано на скриншоте справа. В этой лабораторной работе вы решите все эти проблемы.

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

Оказывается, TalkBack используют не только слепые, но и многие люди с нарушениями зрения. Или даже те, кто просто хочет дать глазам отдохнуть!

Итак, доступность — для всех! В этом задании вы опробуете TalkBack и обновите приложение для корректной работы с ним.

Шаг 1: Установка и запуск Accessibility Suite

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

  1. Откройте Play Маркет.
  2. Найдите Accessibility Suite . Убедитесь, что это правильное приложение от Google.
  3. Если он не установлен, установите Accessibility Suite.
  4. Чтобы включить TalkBack на устройстве, перейдите в раздел «Настройки» > «Специальные возможности» и включите TalkBack, выбрав «Использовать службу» . Как и сканер доступности, TalkBack требует разрешения для чтения содержимого экрана. После того, как вы примете запрос на разрешение, TalkBack предложит вам список обучающих материалов, которые помогут вам эффективно использовать TalkBack.
  5. Остановитесь здесь и пройдите обучающие курсы, хотя бы для того, чтобы узнать, как отключить TalkBack, когда закончите работу.
  6. Чтобы выйти из учебника, нажмите кнопку «Назад», чтобы выбрать его, а затем дважды коснитесь любого места на экране.
  1. Исследуйте приложение GDG Finder с TalkBack. Обратите внимание на места, где TalkBack не даёт вам полезной информации об экране или элементе управления. Вы исправите это в следующем упражнении.

Шаг 2: Добавьте описание контента

Дескрипторы контента — это описательные метки, поясняющие значение представлений. Большинство ваших представлений должны иметь описания контента.

  1. Запустив приложение GDG Finder и включив Talback, перейдите на экран «Применить», чтобы запустить GDG .
  2. Нажимаю на главное изображение... и ничего не происходит.
  3. Откройте add_gdg_fragment.xml .
  4. В ImageView добавьте атрибут дескриптора содержимого, как показано ниже. Строка stage_image_description предоставлена в файле strings.xml .
android:contentDescription="@string/stage_image_description"
  1. Запустите приложение.
  2. Перейдите в раздел «Применить», чтобы запустить GDG , и нажмите на изображение. Вы услышите краткое описание изображения.
  3. [Необязательно] Добавьте описания контента для других изображений в этом приложении. В производственном приложении все изображения должны иметь описания контента.

Шаг 3: Добавьте подсказки в редактируемые текстовые поля.

Для редактируемых элементов, таких как EditText , можно использовать android:hint в XML, чтобы помочь пользователям понять, что вводить. Подсказка всегда отображается в пользовательском интерфейсе, поскольку это текст по умолчанию в поле ввода.

  1. Все еще в add_gdg_fragment.xml .
  2. Добавьте описания контента и подсказки, используя приведенный ниже код в качестве руководства.

Добавить в textViewIntro :

android:contentDescription="@string/add_gdg"

Добавьте в текст редактирования соответственно:

android:hint="@string/your_name_label"

android:hint="@string/email_label"

android:hint="@string/city_label"

android:hint="@string/country_label"

android:hint="@string/region_label"
  1. Добавьте описание содержимого в labelTextWhy .
android:contentDescription="@string/motivation" 
  1. Добавьте подсказку к EditTextWhy . После того, как вы маркируете поля редактирования, добавьте описание содержимого к метке и подсказку к полю.
android:hint="@string/enter_motivation"
  1. Добавьте описание содержимого кнопки «Отправить». Все кнопки должны иметь описание того, что происходит при нажатии.
android:contentDescription="@string/submit_button_description"
  1. Запустите свое приложение с включенным Talback и заполните форму, чтобы подать заявку на запуск GDG.

Шаг 4: Создайте группу контента

Для элементов управления пользовательского интерфейса, которые TalkBack должен обрабатывать как группу, можно использовать группировку контента. Связанный контент, сгруппированный вместе, объявляется вместе. Таким образом, пользователям вспомогательных технологий не придётся так часто пролистывать, сканировать или ждать, чтобы увидеть всю информацию на экране. Это не влияет на внешний вид элементов управления на экране.

Чтобы сгруппировать компоненты пользовательского интерфейса, заключите их в ViewGroup , например LinearLayout . В приложении GDG Finder элементы labelTextWhy и editTextWhy отлично подходят для группировки, поскольку они семантически связаны.

  1. Откройте add_gdg_fragment.xml .
  2. Оберните элементы LabelTextWhy и EditTextWhy в LinearLayout , чтобы создать группу контента. Скопируйте и вставьте код ниже. Этот LinearLayout уже содержит часть необходимых вам стилей. (Убедитесь, что button находится ВНЕ LinearLayout .)
<LinearLayout android:id="@+id/contentGroup" android:layout_width="match_parent"
            android:layout_height="wrap_content" android:focusable="true"
            app:layout_constraintTop_toBottomOf="@id/EditTextRegion"
            android:orientation="vertical" app:layout_constraintStart_toStartOf="@+id/EditTextRegion"
            app:layout_constraintEnd_toEndOf="@+id/EditTextRegion"
            android:layout_marginTop="16dp" app:layout_constraintBottom_toTopOf="@+id/button"
            android:layout_marginBottom="8dp">

     <!-- label and edit text here –>

<LinearLayout/>
  1. Выберите Код > Переформатировать код , чтобы правильно задать отступ для всего кода.
  2. Удалите все поля макета из labelTextWhy и editTextWhy .
  3. В labelTextWhy измените ограничение layout_constraintTop_toTopOf на contentGroup .
app:layout_constraintTop_toTopOf="@+id/contentGroup" />
  1. В editTextWhy измените ограничение layout_constraintBottom_toBottomOf на contentGroup .
app:layout_constraintBottom_toBottomOf="@+id/contentGroup"
  1. Ограничьте EditTextRegion и Button группой contentGroup , чтобы избавиться от ошибок.
app:layout_constraintBottom_toTopOf="@+id/contentGroup"
  1. Добавьте поля к LinearLayout . При желании извлеките это поле как измерение.
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"

Если вам нужна помощь, сверьте свой код с add_gdg_fragment.xml в коде решения.

  1. Запустите приложение и изучите экран «Применить для запуска GDG» с помощью TalkBack.

Шаг 5: Добавьте живой регион

В настоящее время надпись на кнопке «Отправить» выглядит нормально . Было бы лучше, если бы кнопка имела одну надпись и описание до отправки формы, а затем динамически меняла их на другие после нажатия кнопки пользователем и отправки формы. Это можно реализовать с помощью динамической области.

Динамическая область указывает службам доступности, следует ли уведомлять пользователя об изменении представления. Например, уведомление пользователя о неверном пароле или сетевой ошибке — отличный способ сделать приложение более доступным. В этом примере, для простоты, вы уведомляете пользователя об изменении состояния кнопки «Отправить».

  1. Откройте add_gdg_fragment.xml .
  2. Измените назначение текста кнопки на «Отправить» , используя предоставленный ресурс строки submit .
android:text="@string/submit"
  1. Добавьте к кнопке активную область, установив атрибут android:accessibilityLiveRegion . По мере ввода текста доступно несколько вариантов его значения. В зависимости от важности изменения вы можете выбрать, прерывать ли пользователя. При значении «assertive» службы специальных возможностей прерывают текущую речь, чтобы немедленно объявить об изменениях в этом представлении. Если установлено значение «none», никакие изменения не объявляются. При значении «polite» службы специальных возможностей объявляют об изменениях, но ждут своей очереди. Установите значение «polite».

android:accessibilityLiveRegion="polite"
  1. В добавленном пакете откройте AddGdgFragment.kt .
  2. Внутри showSnackBarEvent Observer после завершения отображения SnackBar задайте новое описание содержимого и текст для кнопки.
binding.button.contentDescription=getString(R.string.submitted)
binding.button.text=getString(R.string.done)
  1. Запустите приложение и нажмите кнопку. К сожалению, кнопка и шрифт слишком маленькие!

Шаг 6: Исправление стиля кнопки

  1. В add_gdg_fragment.xml измените width и height кнопки на wrap_content , чтобы была видна вся надпись и кнопка имела подходящий размер.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
  1. Удалите атрибуты backgroundTint , textColor и textSize из кнопки, чтобы приложение использовало лучший стиль темы.
  2. Удалите атрибут textColor из textViewIntro . Цвета темы должны обеспечивать хороший контраст.
  3. Запустите приложение. Обратите внимание на гораздо более удобную кнопку «Отправить» . Нажмите «Отправить» и обратите внимание, как кнопка изменится на «Готово» .

Чипы — это компактные элементы, представляющие атрибут, текст, сущность или действие. Они позволяют пользователям вводить информацию, выбирать варианты, фильтровать контент или запускать действие.

Виджет Chip — это тонкая оболочка для ChipDrawable , которая содержит всю логику компоновки и отрисовки. Дополнительная логика предназначена для поддержки сенсорного управления, мыши, клавиатуры и навигации с помощью специальных возможностей. Основной виджет «Чип» и значок закрытия считаются отдельными логическими подвидами и содержат собственное поведение и состояние навигации.

Чипы используют элементы рисования. Элементы рисования Android позволяют рисовать изображения, фигуры и анимацию на экране, и они могут иметь фиксированный или динамический размер. Вы можете использовать изображения в качестве элементов рисования, например, изображения в приложении GDG. Кроме того, вы можете использовать векторные рисунки для рисования всего, что только можете себе представить. Существует также элемент рисования с изменяемым размером, называемый 9-patch drawable , который не рассматривается в этой практической работе. Логотип GDG, находящийся в файле drawable/ic_gdg.xml , — это ещё один элемент рисования.

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

Шаг 1: Добавьте фишки в список GDG

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

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

  1. Откройте fragment_gdg_list.xml .
  2. Создайте объект com.google.android.material.chip.ChipGroup внутри HorizontalScrollView. Установите его свойство singleLine в true , чтобы все фишки были выстроены на одной горизонтально прокручиваемой строке. Установите свойство singleSelection в true , чтобы можно было выбрать только одну фишку в группе одновременно. Вот код.
<com.google.android.material.chip.ChipGroup
    android:id="@+id/region_list"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:singleSelection="true"
    android:padding="@dimen/spacing_normal"/>
  1. В папке макета создайте новый файл ресурсов макета с именем region.xml для определения макета для одного Chip .
  2. В файле region.xml замените весь код макетом для одного Chip , как показано ниже. Обратите внимание, что этот Chip — компонент Material. Также обратите внимание, что галочка появляется, если задать свойство app:checkedIconVisible . Возникнет ошибка из-за отсутствия цвета selected_highlight .
<?xml version="1.0" encoding="utf-8"?>

<com.google.android.material.chip.Chip
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Widget.MaterialComponents.Chip.Choice"
        app:chipBackgroundColor="@color/selected_highlight"
        app:checkedIconVisible="true"
        tools:checked="true"/>
  1. Чтобы создать отсутствующий цвет selected_highlight , наведите курсор на selected_highlight , откройте меню намерений и создайте цветовой ресурс для выделенного выделения . Параметры по умолчанию вполне подойдут, поэтому просто нажмите «ОК» . Файл будет создан в папке res/color .
  2. Откройте файл res/color/selected_highlight.xml . В этом списке состояний цвета, закодированном как <selector> , вы можете указать разные цвета для разных состояний. Каждое состояние и связанный с ним цвет закодированы как <item> . Подробнее об этих цветах см. в разделе «Цветовая тематика» .
  1. Внутри элемента <selector> добавьте в список состояний элемент с цветом по умолчанию colorOnSurface . В списках состояний важно всегда охватывать все состояния. Один из способов сделать это — задать цвет по умолчанию.
<item android:alpha="0.18" android:color="?attr/colorOnSurface"/>
  1. Над цветом по умолчанию добавьте item с цветом colorPrimaryVariant и ограничьте его использование только в случае, когда выбранное состояние равно true . Списки состояний обрабатываются сверху вниз, как оператор case. Если ни одно из состояний не подходит, применяется состояние по умолчанию.
<item android:color="?attr/colorPrimaryVariant"
         android:state_selected="true" />

Шаг 2: Отобразите ряд фишек

Приложение GDG создаёт список чипов с указанием регионов, где есть GDG. При выборе чипа приложение фильтрует результаты, отображая только результаты GDG для этого региона.

  1. В поисковом пакете откройте GdgListFragment.kt .
  2. В onCreateView() , непосредственно над оператором return , добавьте наблюдателя для viewModel.regionList и переопределите onChanged() . При изменении списка регионов, предоставляемых моделью представления, чипы необходимо пересоздать. Добавьте оператор для немедленного возврата, если предоставленные data равны null .
viewModel.regionList.observe(viewLifecycleOwner, object: Observer<List<String>> {
        override fun onChanged(data: List<String>?) {
             data ?: return
        }
})
  1. Внутри onChanged() , под проверкой null, назначьте binding.regionList новой переменной с именем chipGroup для кэширования regionList .
val chipGroup = binding.regionList
  1. Ниже создайте новый layoutInflator для накачки чипов из chipGroup.context .
val inflator = LayoutInflater.from(chipGroup.context)
  1. Очистите и пересоберите свой проект, чтобы избавиться от ошибки привязки данных.

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

  1. Создайте переменную children для хранения всех фишек. Назначьте ей функцию сопоставления переданных data для создания и возврата каждой фишки.
val children = data.map {} 
  1. Внутри лямбда-функции map для каждого regionName создайте и расширьте чип. Полный код представлен ниже.
val children = data.map {
   val children = data.map { regionName ->
       val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
       chip.text = regionName
       chip.tag = regionName
       // TODO: Click listener goes here.
       chip
   }
}
  1. Внутри лямбда-выражения, непосредственно перед возвратом chip , добавьте прослушиватель щелчков. При chip по чипу установите его состояние в checked . Вызовите метод onFilterChanged() в viewModel , который запускает последовательность событий, извлекающих результат для этого фильтра.
chip.setOnCheckedChangeListener { button, isChecked ->
   viewModel.onFilterChanged(button.tag as String, isChecked)
}
  1. В конце лямбды удалите все текущие представления из chipGroup , затем добавьте все чипы из children в chipGroup . (Вы не можете обновить чипы, поэтому вам придется удалить и заново создать содержимое chipGroup .)
chipGroup.removeAllViews()

for (chip in children) {
   chipGroup.addView(chip)
}

Ваш завершенный наблюдатель должен выглядеть следующим образом:

   override fun onChanged(data: List<String>?) {
       data ?: return

       val chipGroup = binding.regionList
       val inflator = LayoutInflater.from(chipGroup.context)

       val children = data.map { regionName ->
           val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
           chip.text = regionName
           chip.tag = regionName
           chip.setOnCheckedChangeListener { button, isChecked ->
               viewModel.onFilterChanged(button.tag as String, isChecked)
           }
           chip
       }
       chipGroup.removeAllViews()

       for (chip in children) {
           chipGroup.addView(chip)
       }
   }
})
  1. Запустите приложение и выполните поиск по запросу GDGS, чтобы открыть экран поиска для использования новых фишек. При нажатии на каждую фишку приложение будет отображать под ней группы фильтров.

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

Шаг 1: Включите ночной режим

Чтобы использовать тёмную тему для своего приложения, измените тему со Light на тему DayNight . Тема DayNight будет светлой или тёмной в зависимости от режима.

  1. В styles.xml, измените родительскую тему AppTheme с Light на DayNight .
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
  1. В методе onCreate() MainActivity вызовите AppCompatDelegate.setDefaultNightMode() , чтобы программно включить темную тему.
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
  1. Запустите приложение и убедитесь, что оно переключилось на темную тему.

Шаг 2: Создайте собственную цветовую палитру для темной темы

Чтобы настроить тёмную тему, создайте папки с квалификатором -night для использования тёмной темы. Например, вы можете настроить определённые цвета в ночном режиме, создав папку с именем values-night .

  1. Воспользуйтесь инструментом выбора цветов на material.io и создайте цветовую палитру для ночной темы. Например, можно взять за основу тёмно-синий цвет.
  2. Создайте и загрузите файл colors.xml .
  3. Переключитесь в режим просмотра файлов проекта , чтобы просмотреть список всех папок вашего проекта.
  4. Найдите папку res и разверните ее.
  5. Создайте папку ресурсов res/values-night .
  6. Добавьте новый файл colors.xml в папку ресурсов res/values-night .
  7. Запустите приложение с включённым ночным режимом, и оно должно использовать новые цвета, которые вы определили для res/values-night . Обратите внимание, что для фишек используется новый вторичный цвет.

Проект Android Studio: GDGFinderFinal .

Поддержка языков с письмом справа налево

  • В манифесте Android установите android:supportsRtl="true" .
  • Вы можете просмотреть RTL-версию в эмуляторе и использовать свой язык для проверки макетов экрана. На устройстве или эмуляторе откройте «Настройки» и в разделе «Параметры разработчика» выберите «Принудительно использовать макет RTL».
  • Замените ссылки на Left и Right ссылками на Start и End .
  • Отключите зеркалирование для рисуемых объектов, удалив android:autoMirrored="true" .
  • Выберите «Рефакторинг» > «Добавить поддержку RTL, где это возможно», чтобы позволить Android Studio выполнить всю работу за вас.
  • Используйте папки «значения-код языка» для хранения ресурсов, специфичных для конкретного языка.

Сканирование на доступность

Дизайн для TalkBack с описаниями контента

  • Установите Android Accessibility Suite от Google, в который входит TalkBack.
  • Добавьте описания содержимого ко всем элементам пользовательского интерфейса. Например:
    android:contentDescription="@string/stage_image_description"
  • Для редактируемого элемента, такого как EditText , используйте атрибут android:hint в XML, чтобы дать намек на пользователя о том, что печатать.
  • Создать группы контента, обернув связанные элементы в группу VIEW.
  • Создайте живой регион, чтобы дать пользователям дополнительную обратную связь с android:accessibilityLiveRegion .

Используйте чипы для реализации фильтра

  • Чипы - это компактные элементы, которые представляют атрибут, текст, сущность или действие.
  • Чтобы создать группу чипов, используйте com.google.android.material.chip.ChipGroup .
  • Определите макет для одного com.google.android.material.chip.Chip .
  • Если вы хотите, чтобы ваши чипсы изменили цвета, предоставьте список цветовых состояний в качестве <selector> с Catherful Colors:
    <item android:color="?attr/colorPrimaryVariant"
    android:state_selected="true" />
  • Свяжите чипы с живыми данными, добавив наблюдателя в данные в модели представления.
  • Чтобы отобразить фишки, создайте надув для группы чипов:
    LayoutInflater.from(chipGroup.context)
  • Создайте фишки, добавьте прослушиватель кликов, который запускает желаемое действие, и добавьте фишки в группу чипов.

Поддержка темного режима

  • Используйте DayNight AppTheme , чтобы поддержать Dark Mode.
  • Вы можете программно установить режим Dark:
    AppCompatDelegate.setDefaultNightMode()
  • Создайте папку ресурса Res/значения-ночи, чтобы предоставить пользовательские цвета и значения для темного режима.

Документация разработчика Android:

Другие ресурсы:

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

  • Назначьте домашнее задание, если это необходимо.
  • Сообщите студентам, как отправлять домашние задания.
  • Оценка домашних заданий.

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

Если вы работаете над этим CodeLab самостоятельно, не стесняйтесь использовать эти домашние задания, чтобы проверить свои знания.

Вопрос 1

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

▢ Замените Left и Right в свойствах на Start и End

▢ Переключитесь на язык RTL

▢ Убедитесь, что все значки используют android:autoMirrored="true"

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

Вопрос 2

Какой из следующих инструментов доступности встроен с большинством устройств Android?

▢ Talkback

▢ Сканер доступности

▢ В Android Studio, Refactor> Добавьте поддержку RTL, где это возможно

▢ Lint

Вопрос 3

Что из перечисленного не относится к чипсам?

▢ Вы отображаете чипы как часть ChipGroup .

▢ Вы можете предоставить список цветовых состояний для группы ChipGroup .

▢ Чипы - это компактные элементы, которые представляют вход, атрибут или действие.

▢ Вы всегда должны включать DarkTheme , если ваше приложение использует чипсы.

Вопрос 4

Какая тема дает вам стиль для темных и легких режимов?

DayNight

DarkTheme

DarkAndLightTheme

Light

Вопрос 5

Что такое живой регион?

▢ Узел, который содержит информацию, которая важна для пользователя

▢ Область экрана, которая изменяет форму в соответствии с рекомендациями материала

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

▢ Анимированная натяжка