android studio меню настроек
Меню в Android приложениях
Android поддерживает два типа меню : главное и контекстное (других пока не придумано). В старых телефонах имеется отдельная кнопка Menu, нажатие которой открывает главное меню. Начиная с версии Android 3.0 (уровень API 11) наличие отдельной кнопки Меню больше не требуется; Android приложения перестали зависеть от традиционной панели меню из 6 пунктов. Вместо нее в приложениях появилась строка действий ActionBar с часто используемыми действиями пользователя. Несмотря на то, что интерфейс и поведение некоторых пунктов меню изменились, бизнес-логика определения набора действий по-прежнему основана на API-интерфейсах класса Menu. Таким образом, начиная с версии Android 3.0 пункты меню размещаются в строке действий ActionBar в виде сочетания отображаемых на экране вариантов действий и иконки из трёх вертикальных точек, которую расположили в правой верхней части приложения. При нажатии на иконку открывается отдельное окно, в котором вертикально отображается список дополнительных вариантов выбора.
Контекстное меню появляется при длительном нажатии пальцем на каком-либо элементе интерфейса приложения. В контекстном меню содержатся действия, которые затрагивают выбранный контент или контекстный кадр. Пункты контекстных действий, затрагивающие выбранный контент, располагаются в строке в верхней части экрана.
В данной статье рассмотрим пример использования первого типа меню (на новых устройствах) под управлением Android 4.0 и выше. К пунктам меню добавим иконки. При этом, один из пунктов меню с иконкой тележки (ic_shopping_cart_black.png) сделаем видимым, а остальные скрытыми. Для этого создадим новый модуль/проект p06menu, интерфейс которого представлен на следующем скриншоте. В верхней части приложения располагается меню, в нижней части высвечивается всплывающее сообщение, создаваемое классом Toast при выборе какого-либо пункта меню. То есть, в примере можно будет выбрать какой-либо пункт меню и увидеть связанное с ним сообщение.
Определение интерфейса
В интерфейсе приложения (activity_main.xml) создаваемый по умолчанию компонент TextView с текстом «Hello World» удаляем. После этого подключаем панель инструментов. Для этого в панели Palette (нижний скриншот) открываем вкладку Containers и перетаскиваем в панель Component Tree компонент AppBarLayout. Компонент Toolbar будет добавлен автоматически.
Исходный текст файла конфигурации интерфейса activity_main.xml можно подкорректировать так, чтобы он выглядел следующим образом :
Листинг activity_main.xml
Иконки пунктов меню
Прежде чем формировать меню, загрузим в директорию модуля res/drawable следующие иконки (более 6) :
Для этого можно использовать Ctrl+C, Ctrl+V. Копирование изображений в проект подробно рассмотрено здесь.
Создание меню
В примере будем использовать ресурсный файл меню, т.е. для описания меню будет использоваться XML файл, располагаемый в директории проекта res/menu/. Для формирования ресурсного XML файла описания меню выбираем в Studio New/Android Resource File, и, в открывшемся окне, определяем наименование «main_menu». Нажимаем OK, и в директории res/menu/ будет создан файл main_menu.xml.
Описание меню включает следующие секции :
В следующем листинге файла main_menu.xml представлены 2 первых пункта меню нашего примера. Пункт меню с тележкой (Cart) определяем постоянно видимым (app:showAsAction=»always»), а пункт меню Call – невидимым (app:showAsAction=»never»); он будет доступен при открытии главного меню.
Каждый пункт меню включает следующие атрибуты :
• id идентификатор пункта меню, по которому приложение может распознать выделенный пользователем пункт меню;
• title отображаемый текст;
• icon отображаемый рядом с текстом иконка;
• showAsAction определяет поведение меню в ActionBar;
• enabled определение доступности пункта меню (не используется в примере);
• orderInCategory порядок отображения в ActionBar (не используется в примере);
• titleCondensed атрибут применяется в том случае, если обычный заголовок слишком широкий и не «помещается» в выбранном элементе меню (не используется в примере).
Важный атрибут app:showAsAction определяет поведение меню в ActionBar. Значение never означает, что элемент меню не должен выводиться в заголовке ActionBar, а только во всплывающем меню. Если установить значение always, то пункт меню будет представлен в заголовке приложения (ActionBar). Также доступны значения ifRooms (если позволяет место), withText и collapseActionView.
Конечно же, следовало бы локализовать меню в примере. Для этого необходимо определить наименования пунктов меню в ресурсном файле res/values/strings.xml и подключить их в опциях android:title пунктов меню. Но для данного примера, где рассматривается меню, локализация пунктов меню не имеет значения.
Группирование пунктов меню
Атрибут checkableBehavior может иметь одно из трех следующих значений :
• single только один пункт из группы можно пометить (переключатель);
• all все пункты группы можно пометить (флажки);
• none нельзя ни один пункт из группы пометить.
Интерфейс меню
Среда разработки Android Studio представляет описание файла меню main_menu.xml в двух режимах ( Design | Text ) подобно описанию интерфейса activity_main.xml. На следующем скриншоте main_menu.xml представлен в режиме Design. В графическом интерфейсе файла main_menu.xml изображены все пункты меню. При этом в заголовке ActionBar располагается первый пункт меню с изображением тележки, рядом с которой располагается иконка с вертикальным изображением трех точек. При нажатии на эту иконку в режиме run-time будет открыто (представленное на скриншоте) вертикально расположенное в ActionBar меню.
В панели Component Tree представлена иерархическая структура меню. Рядом с каждым пунктом меню располагается иконка с предупреждением о необходимости локализации текста, о чем было сказано выше.
Поскольку в меню используются иконки, то необходимо внести изменения в файл проекта res/values/styles.xml и в файл студии Gradle Scripts/p06menu.
Листинг res/values/styles.xml
Внесенные в файл изменения выделены жирным стилем.
Листинг Gradle Scripts/p06menu
В директории Gradle Scripts располагаются некоторые файлы модулей. Для того, чтобы в меню наряду с текстом отображались иконки необходимо в файл Gradle Scripts/p06menu примера добавить строку.
В следующем листинге представлен текст файла Gradle Scripts/p06menu. Последняя выделенная строка необходима, чтобы в пунктах меню можно было использовать иконки. Согласуйте номер со своей версией SDK.
Обработчики событий
Для того, чтобы приложение как-то реагировало на выбор пункта меню, необходимо к нему подключить соответствующий обработчик. Это можно сделать двумя способами. Первый, самый простой, связан с созданием метода в активности MainActivity.java и подключение его в файле описания пункта меню. Подключим подобный обработчик события к пункту меню Help. Для этого в модуль MainActivity.java включим метод onHelpClick. Обратите внимание на описание метода : он должен быть public и принимать параметр типа MenuItem. Метод выводит сообщение с использованием класса Toast.
Для подключения к пункту меню метода обработки сообытия необходимо в атрибуте описания пункта меню android:onClick определить его наименование.
Второй способ подключения обработчиков к пунктам меню связан с методом onOptionsItemSelected. Активность MainActivity.java включает данный метод, но он пустой. Необходимо его переписать. Ниже представлен листинг метода нашего примера, в котором в зависимости от выбранного пункта меню выводится соответствующее сообщение. В качестве параметра метод принимает объект типа MenuItem.
Подключение меню
MainActivity.java может иметь только одно меню. Если приложение имеет несколько экранов, то у каждой активности должно быть отдельное меню со своими настройками. Для подключения меню к активности необходимо переписать метод активности onCreateOptionsMenu. В следующем листинге представлен код активности с двумя методами onCreate и onCreateOptionsMenu (представленные выше методы не включены в листинг). В первом методе создается активность, во втором методе к активности подключается меню. Метод onCreateOptionsMenu вызывается активностью один только раз при первом открытии меню. Но, поскольку, один из пунктов меню (Cart) видимый, то метод вызывается сразу же, при формировании интерфейса приложения.
В методе onCreateOptionsMenu сначала создается объект типа MenuInflater. После этого вызывается метод этого объекта inflate, которому в качестве параметров передаются ресурсное меню (R.menu.menu_main) и объект класса Menu. Если объект menu имеет тип MenuBuilder, используется рефлексия, чтобы вызвать метод объекта setOptionalIconsVisible.
Примечание : Android Studio предупреждает, что рефлексия не поддерживается системой и в будущем может не работать (в примере с текущей версией системы работает).
Код с рефлексией, используемый для включения в пункты меню иконок, можно было бы заменить кодом, представленным ниже.
Но, к сожалению, я не смог сразу же заставить этот код работать : здесь Android Studio ругалась на метод setOptionalIconsVisible, который в примере был вызван с использованием рефлексии. Полагаю, что как только эта проблема будет решена, то в статью будут внесены соответствующие изменения и данные строки Вы не увидите.
После старта примера Вы должны увидеть интерфейс приложения, представленный на следующем скриншоте. Здесь меню открыто. На первом скриншоте интерфейса приложения отображено сообщение и меню свернуто.
Android studio меню настроек
В шаблоне Empty Activity нет меню, поэтому мы создадим его сами. Это поможет вам понять принцип работы и получить общее представление о проекте. Запоминать названия классов, методов и код для обработки выбора пунктов меню необязательно. В других шаблонах меню будет встроено и вы можете сразу использовать его.
Создайте новый проект на основе Empty Activity и запустите его. Никакого меню пока нет.
Создадим несколько строковых ресурсов в файле res/values/strings.xml, которые будут отвечать за пункты меню:
Откроем файл MainActivity. Сейчас в нём только один метод onCreate(). Добавим новый метод onCreateOptionsMenu(). Именно данный метод отвечает за появление меню у активности. Сразу после метода onCreate() начинайте вводить первые символы метода и дальше студия сама покажет список подходящих методов.
Найдите нужный метод и заготовка будет создана автоматически.
Добавляем в заготовку метод, который берёт данные из ресурсов меню и преобразует их в пункты меню на экране.
В методе inflate() вы указываете ресурс меню (R.menu.menu_main) и объект класса Menu.
Запустите проект. Теперь в правой части заголовка вы увидите значок из трёх точек, выстроенных в вертикальную линию. Нажмите на значок, чтобы увидеть пункт меню Settings.
Как не трудно догадаться, элемент item отвечает за отдельный пункт меню. Добавим ещё три пункта по такому же принципу, меняя только идентификатор и текст для меню:
Запустите проект и попробуйте снова вызвать меню. Вы увидите три новых пункта.
Параметры id и title не нуждаются в объяснениях. Параметр orderInCategory позволяет задать свой порядок вывода пунктов меню. Предположим вы создали пять пунктов меню, но пока не определились с порядком их вывода на экране. Чтобы не перемещать постоянно целые блоки кода для пунктов меню в нужном порядке, можно воспользоваться данным параметром.
И, наконец, важный атрибут app:showAsAction определяет поведение меню в ActionBar. Значение never означает, что элемент меню не должен выводиться в заголовке, а только в всплывающем меню, т.е. находиться за тремя точками. Если вы установите значение always, то пункт Settings сразу появится в заголовке вашего приложения. Также доступны значения ifRooms, withText и collapseActionView. Попробуйте самостоятельно. Например, ifRoom выводит пункт меню, если позволяет место. Если пунктов будет много, то они будут только мешаться. Как правило, в таком варианте выводят очень короткое слово или значок для частых операций, чтобы избежать лишнего щелчка на три точки.
Обратите внимание на атрибут app:showAsAction, который относится к пространству имён xmlns:app=»http://schemas.android.com/apk/res-auto». Было время, когда такого пространства имён не существовало и в проектах использовался атрибут android:showAsAction из стандартного пространства имён. Если студия будет ругаться на ошибку, то отредактируйте код.
Пока пункты меню не выполняют полезной работы. Любое нажатие на пункт просто закрывает меню без видимых последствий. Мы ещё не написали код для обработки нажатий.
Выбор пунктов меню
Мы научились создавать меню. Но пока оно бесполезно, так как пункты меню никак не реагируют на наши нажатия. Для обработки нажатий пунктов меню служит другой метод onOptionsItemSelected(). Добавим метод по такому же принципу, как для предыдущего примера. Получим заготовку.
Параметр item отвечает за пункт меню. Вам следует получить идентификатор меню через метод getItemId() и указать для него код (в Kotlin вместо метода используется свойство itemId). Так как обычно меню состоит из нескольких пунктов, то удобно использовать конструкцию when. Для вывода информации воспользуемся текстовой меткой. Добавьте на экран активности компонент TextView. Можете использовать имеющийся TextView с надписью «Hello World!», только присвойте ему идентификатор.
Добавим код в заготовку для выбранного пункта меню:
Запустите приложение, вызовите меню и выберите любой пункт меню. В текстовом поле должно появиться сообщение.
Переключатели
Внешний вид пунктов меню можно изменить на вид с переключателями. Для этого нужно добавить элемент group с атрибутом android:checkableBehavior=»single»:
Большого смысла в этом режиме я не вижу. И рассматривать его не будем.
Режим Design
В Android Studio 2.2 добавили графический режим построения меню, которых похож на панель инструментов для добавления новых компонентов на экран. У меню панель состоит из четырёх элементов: Menu Item, Search Item, Menu, Group.
Принцип тот же, выбираете нужный элемент и перетаскиваете его на экран в область меню. Если вы изучили ручное создание меню, то данный способ не вызовет у вас затруднений. С его помощью можно быстро набросать структуру меню, а затем подправить вручную.
Итак, вы получили базовые навыки работы с меню, достаточных для большинства случаев. Если хотите узнать больше, то почитайте дополнительную информацию о меню в разделе Теория.
Пример на Java
Код на Java не сильно отличается. Создание элементов меню на XML остаётся без изменений. Осталось только написать кода в классе активности.
Выберите в студии меню Code | Override Methods. и в следующим окне начинайте вводить название метода по первым буквам. Можно вводить по первым заглавным буквам, т.е. ocom (onCreateOptionsMenu), чтобы быстро найти нужную строку. Нажимаем кнопку OK и получаем заготовку.
Добавляем в заготовку метод, который берёт данные из ресурсов меню и преобразует их в пункты меню на экране.
Добавим код в заготовку для выбранного пункта меню:
Запустите приложение, вызовите меню и выберите любой пункт меню. В текстовом поле должно появиться сообщение.
Существует альтернативный способ через XML, похожий на обработку щелчков кнопки (начиная с Android 3.0). Вы можете добавить атрибут android:onClick в ресурсах меню, и вам не нужно использовать вызов метода onOptionsItemSelected(). При помощи android:onClick вы можете указать нужный метод при выборе пункта меню. Добавьте данный атрибут к пункту Settings
Теперь в коде активности напишем следующее:
Полный список
— создаем пункты меню c ID
— группируем и сортируем пункты меню
Чтоб показать как используются все эти параметры, создадим приложение. На экране будет TextView и CheckBox:
— TextView будет отображать какой пункт меню был выбран
— CheckBox будет определять показывать обычное меню или расширенное. Это будет реализовано с помощью групп меню.
Project name: P0141_MenuAdv
Build Target: Android 2.3.3
Application name: MenuAdv
Package name: ru.startandroid.develop.menuadv
Create Activity: MainActivity
Откроем main.xml, присвоим ID существующему TextView, сотрем его текст и создадим CheckBox. Код:
Открываем MainActivity.java и класс MainActivity заполняем следующим кодом:
Не забудьте обновить импорт (CTRL+SHIFT+O).
Давайте разбирать написанное. Мы используем следующие методы:
В методе onCreateOptionsMenu мы добавляем 6 пунктов меню. Обратим внимание на параметры метода Add.
Второй параметр – ID пункта меню. В обработчике используется для определения какой пункт меню был нажат. Будем использовать его в onOptionsItemSelected.
Третий параметр – определяет позицию пункта меню. Этот параметр используется для определения порядка пунктов при отображении меню. Используется сортировка по возрастанию, т.е. от меньшего order к большему.
Четвертый параметр – текст, который будет отображаться на пункте меню. Тут все понятно.
В метод onPrepareOptionsMenu передается объект Menu и мы можем работать с ним. В данном примере вызываем setGroupVisible. Этот метод позволяет скрывать\отображать пункты меню. На вход подается два параметра – ID группы и boolean-значение. В качестве ID группы мы пишем – 1 (та самая группа с в которой находятся пункты copy, paste и exit), а в качестве boolean параметра используем состояние CheckBox. Если он включен, то пункты меню (из группы с будут отображаться, если выключен – не будут.
Сохраним все и запустим приложение.
«Обычное» меню:
«Расширенное» меню
В зависимости от состояния CheckBox в меню видно 3 или 6 пунктов.
Обратите внимание на порядок пунктов. Они отсортированы по параметру order по возрастанию. Если order у нескольких пунктов совпадает, то эти пункты размещаются в порядке их создания в методе onCreateOptionsMenu.
При нажатии на какой-либо пункт меню срабатывает метод onOptionsItemSelected. В нем мы выводим в TextView информацию о нажатом пункте. Можете сверить эту информацию с тем, что мы кодили при создании пунктов меню. Все параметры должны совпадать. Порядок, для удобства, я сделал такой же как и в методе add: groupId, itemId, order, title.
Попробуйте добавить еще несколько пунктов в меню, чтобы их стало больше шести. И обратите внимание, как они отобразятся.
Для упрощения кода я использовал напрямую цифры для ID групп и ID пунктов меню. А вообще рекомендуется использовать константы, в дальнейшем буду использовать их.
XML-меню
Если в папке res нет папки меню, создайте ее. Правой кнопкой на res, выбирайте New > Android Resource Directory, в Resource type выбирайте menu и жмите OK.
В методе onCreateOptionsMenu нам теперь не надо вручную кодить создание каждого пункта, мы просто свяжем menu, который нам дается на вход и наш xml-файл.
С помощью метода getMenuInflater мы получаем MenuInflater и вызываем его метод inflate. На вход передаем наш файл mymenu.xml из папки res/menu и объект menu. MenuInflater берет объект menu и наполняет его пунктами согласно файлу mymenu.xml.
Если захотите скрыть группу, выполняете тот же метод setGroupVisible и передаете туда R.id.group1 в качестве ID группы.
Подробно атрибуты для xml-файла меню можно посмотреть здесь.
Я вам рекомендую опробовать и потестить оба способа созданию меню. Программное создание гибче, а xml сокращает код.
На следующем уроке:
— создадим контекстное меню
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Android studio меню настроек
Поработаем сегодня над меню нашего приложения. Трудно представить приложение, в котором нету хоть какого то меню. Основы работы с ним довольно просты. Раньше меню вызывалось аппаратной кнопкой, сейчас эта кнопка стала сенсорной, но суть работы с ним не поменялась.
Там же сразу можно увидеть и подсказки от Android Studio, которые описывают функционал этих методов.
Само меню в приложениях на Android 4+ (до этого оно вызывалось просто соответствующей кнопкой устройства) выглядит, как 3 вертикальные точки на панели с названием приложения:
Если мы сейчас запустим приложение и нажмем на кнопку меню, то там будет находится всего одна строка с названием Settings. Давайте научимся редактировать и добавлять пункты к меню.
Чтобы это сделать, открываем файл menu_main.xml в папке menu приложения:
Сам файл выглядит так:
Как не сложно догадаться, тег item соответствует созданию одного пункта меню. Сейчас у нас создан один пункт меню и его имя задано не явно, а через ссылку на строковый ресурс:
Перед тем, как добавить в меню свои пункты, давайте создадим для них названия в строковых ресурсах. Открываем файл strings.xml папки values и добавим туда несколько строк:
Вернемся к файлу menu_main.xml и преобразим его. Удаляем пункт Settings и добавляем Пункт 1, Пункт 2 и Пункт 3:
Сейчас при попытке запустить приложение, нас ждет ошибка, чтобы ее устранить, идем в файл MainActivity.java и удаляем оттуда кусочек кода, касающийся уже удаленного пункта меню Settings:
Если сейчас запустить приложения и нажать по кнопке меню, то мы увидим, что оно теперь состоит из 3-х созданных нами пунктов.
На данный момент наши пункты, при нажатии на них, не выполняют никаких функций. Давайте их оживим. Для этого существует уже упомянутый в начале метод onOptionsItemSelected.
Создадим в файле разметки интерфейса activity_main.xml элемент TextView:
Мы создали его для того, чтобы влиять на элемент TextView, делая выбор пунктов меню, чтобы как то визуализировать эти действия (то есть, для наглядности).
Возвращаемся к файлу MainActivity.java и в методе обработки нажатий пунктов onOptionsItemSelected для первых 2-х пунктов настроим действие, которое будет применять элементу TextView различный текст, а 3-й пункт сделаем кнопкой выхода из программы.
В методе onOptionsItemSelected объявим объект TextView, привяжем его к созданному в activity_main.xml элементу TextView, и с помощью команды switch (id) настроим действие нажатия каждого пункта:
Полный код MainActivity.java должен выглядеть так:
Все готово, запускаем приложение и любуемся нашими послушными кнопочками:).
Конечно, это далеко не предел возможностей работы с меню, но для начала то хватит. Удачи!