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

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

  1. Вставка view в панели инструментов, обеспечивая правильное размещение, размер изображения и пространство между соседями
  2. Добавление слушателя нажатия view
  3. Определение визуальной обратной связи при щелчке (например, изменение цвета фона или пульсации)

Все, что остается сделать — определить текст заголовка и значок drawable в нашем  файле макета меню, инфлейтить этот макет в onCreateOptionsMenu() и обрабатывать щелчки в onOptionsItemSelected(). Если вы когда-либо работали с пунктами меню — для вас здесь нет ничего нового. Если не работали — смотрите этот урок.

Разметка пункта меню:

Реализация в коде активити:

Вот так это выглядит:

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

Первое, что приходит в голову — динамично менять картинку drawable, используемую в пункте меню. Мы можем схитрить и просто подставлять 11 различных символов drawables для нашего приложения в цикле:

  • icon with no red circle
  • icon with empty red circle
  • icon with red circle and «1»
  • icon with red circle and «2»
  • icon with red circle and «9»

Это могло бы быть проще для нас как разработчиков (но больше работы для нашего дизайнера), но дополнительные ресурсы начнут раздувать размер нашего apk. Вместо этого мы можем использовать кастомные view, чтобы достигнуть того же самого эффекта с меньшим количеством ресурсов.

Определение Custom View

Ключевым моментом для кастомного view является использование app:actionLayout вместо android:icon в нашем файле ресурсов меню.

Далее мы сделаем макет кастомного view в папке layouts.

Теперь у нас есть красный круг — FrameLayout, который содержит TextView нашего счетчика оповещения . Мы также имеем ImageView нашего значка предупреждения. Наконец, мы должны обернуть все в корневой FrameLayout. Еще нам необходимо жестко закодировать размер нашего значка согласно правил материального дизайна. Мы определяем размеры иконки в файле dimens.xml.

Если мы запустим приложение, мы увидим новый значок, но возникают две проблемы:

  1. onOptionsItemSelected не вызывается при нажатии на кастомный пункт меню
  2. Значок визуально не реагирует на клики (т. е. нет пульсаций)

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

Использование Custom View

Мы хотим настраивать кастомное view в нашем меню при каждом отображении. Таким образом, вместо настройки его в onCreateOptionsMenu, мы будем делать некоторую работу внутри onPrepareOptionsMenu. Так как наш пункт меню — просто заполненный макет, мы можем работать с ним как с любым макетом. Например, мы можем найти view id.

Мы получаем доступ к корневому view-элементу этого пункта меню, находим сначала пункт меню, а затем вызываем getActionView. Теперь мы сможем найти красный круг и счетчик оповещений в поле textview.

Затем мы обновляем значок оповещения, когда пользователь нажимает на кнопку «обновить» пункта меню:

У нас теперь есть обновление пункта меню:

Фиксим траблы

Как я сказал прежде, у нас еще есть две проблемы:

  1. onOptionsItemSelected не вызывается при нажатии на кастомный пункт меню
  2. Значок визуально не реагирует на клики (т. е. нет пульсаций)

Давайте сначала займемся первой. По некоторым причинам, когда наш пункт меню зависит от  app:actionLayout вместо  android:icon, onOptionsItemSelected не будет вызываться для кастомного элемента меню. это известная проблема. Решение – просто добавить наш собственный слушатель ClickListener корневому view и вручную вызвать onOptionsItemSelected. Будем также сбрасывать счетчик предупреждений, когда пользователь щелкает пункт оповещения в меню:

Теперь если вы запустите приложение, то обнаружите, что нужно нажать значок предупреждения несколько раз, прежде чем он отреагирует. Выберем «Показать границы макета» в параметрах разработчика и сразу же увидим проблему:

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

Возвращаясь к рекомендациям по Материальному дизайну, мы должны установить новые размеры для корневого view 48dp высоты и ширины.

Это успешно увеличивает нашу область щелчка.

Последнее, что нам нужно сделать, это включить визуальную обратную связь при выборе пункта меню. Для Lollipop+ устройства это означает рябь; для более старых устройств это означает изменение цвета фона.К счастью для нас, эта функциональность уже содержится в  attr/selectableItemBackgroundBorderless. Поэтому все, что нам нужно это новое view в нашем файле макета, которому мы можем задать этот атрибут:

Идеально. Все выглядит хорошо. Пульсация хорошо смотрится на нашем устройстве Android 22 и изменение цвета фона выглядит хорошо на нашем устройстве Android 19.

API 19 device

API 22 device

API 22 device

Последний штрих

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

Ripple границы на стандартном меню

Ripple границы на стандартном меню

Ripple границы кастомного меню

Ripple границы кастомного меню

Чтобы исправить это, нам нужно сделать несколько проб и ошибок, чтобы выяснить, правильный размер границы ряби. Мы его будем предоставлять для API 23+ устройств. Наконец, мы будем обновлять макет, чтобы использовать этот новый размер (вместо того, чтобы просто установить свойство match_parent для ripple view). Вы можете проверить самостоятельно, но на API 23+ Эта ряби граница должна быть 28dp.

Теперь у нас эффект ряби кастомного пункта меню такого же размера, как и у стандартного пункта меню.

Вот так. Наше решение в настоящее время работает на всех последних версий Android. Не стесняйтесь загрузить этот образец здесь.

API 19 device

API 19 device

API 22 device

 

API 24 device

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

Кастомные view для пунктов меню в приложении андроид обновлено: Ноябрь 29, 2016 автором: admin

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*
*
Website