Как сделать меню на андроиде. Создание меню. Вход в инженерное меню

Создание меню

Последнее обновление: 26.02.2017

Меню в приложениях представляет класс android.view.Menu , и каждая activity ассоциируется с объектом этого типа. Объект android.view.Menu может включать различное количество элементов, а те в свою очередь могут хранить подэлементы.

Определение меню в xml

Меню, как и файлы интерфейса или изображений, также представляет собой ресурс. По умолчанию файлы меню находятся в проекте в каталоге res/menu .

При создании нового проекта с Empty Activity у нас нет никакого каталога res/menu и соответственно нет ресурсов меню, но мы можем их добавить вручную. Для этого нажмем правой кнопкой мыши в проекте на каталог res и далее в открывшемся списоке выберем пункт New -> Android Resource File :

После этого в каталоге res будет создан подкаталог menu, в котором будет находиться файл main_menu.xml.

По умолчанию этот файл определяет один пустой элемент menu:

Изменим содержимое файла, определив несколько пунктов:

Тег

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

Элемент представляет объект MenuItem, которой является одним из элементов меню. Этот элемент может содержать внутренний подэлемент

, с помощью которого создается подменю.

Элемент включает следующие атрибуты, которые определяют его внешний вид и поведение:

    android:id : уникальный id элемента меню, который позволяет его опознать при выборе пользователем и найти через поиск ресурса по id

    android:orderInCategory : порядок следования элемента в меню

Наполнение меню элементами

Мы определили меню с тремя элементами, но само определение элементов в файле еще не создает меню. Это всего лишь декларативное описание. Чтобы вывести его на экран, нам надо использовать его в классе Activity. Для этого надо переопределить метод onCreateOptionsMenu . Итак, перейдем к классу MainActivity и изменим его следующим образом:

Package com.example.eugene.menuapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.Menu; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); return true; } }

Метод getMenuInflater получает объект MenuInflater и вызываем его метод inflate() . Этот метод в качестве первого параметра принимает ресурс, представляющий наше декларативное описание меню в xml, и наполняет им объект menu, переданный в качестве второго параметра.

Запустим приложение по умолчанию и нажмем на кнопку меню в правом верхнем углу:

Обработка нажатий в меню

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

Для вывода выбранного элемена меню в файле activity_main.xml определим текстовое поле с id=header:

И изменим класс MainActivity:

Package com.example.eugene.menuapp; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); TextView headerView = (TextView) findViewById(R.id.header); switch(id){ case R.id.action_settings: headerView.setText("Настройки"); return true; case R.id.open_settings: headerView.setText("Открыть"); return true; case R.id.save_settings: headerView.setText("Сохранить"); return true; } return super.onOptionsItemSelected(item); } }

Чтобы понять, какой пункт меню выбран, вначале получаем его идентификатор int id = item.getItemId() . Затем пробегаемся в конструкции switch..case и выбираем нужный вариант и в зависимости от выбора производим определенные действия - в данном случае устанавливаем текст TextView.

Android поддерживает несколько типов меню. Первый - на телефоне есть отдельная кнопка Menu (в старых телефонах), нажатие которой вызывает меню. В новых устройствах отдельную кнопку убрали, заменив на значок меню в виде трёх точек в вертикальной ориентации. Второй тип - контекстное меню, которое появляется при нажатии и удерживания пальца на экране в нужном месте (также можно нажать и удерживать центральную кнопку на телефоне). Контекстное меню в свою очередь может иметь подменю. Сегодня мы познакомимся с первым типом меню. В данной статье будет рассматриваться работа с меню на новых устройствах под управлением Android 4.0 и выше.

В шаблоне Empty Activity нет меню, поэтому мы создадим его сами. Это поможет вам понять принцип работы и получить общее представление о проекте. Запоминать названия классов, методов и код для обработки выбора пунктов меню необязательно. В других шаблонах меню будет встроено и вы можете сразу использовать его.

Создайте новый проект на основе Empty Activity и запустите его. Никакого меню пока нет.

Создадим несколько строковых ресурсов в файле res/values/strings.xml , которые будут отвечать за пункты меню:

Settings Кот Кошка Котёнок

Теперь создайте новую папку menu в папке res res , | New | Directory ). Далее создайте в созданной папке файл menu_main.xml - имя указывает, что меню относится к основной активности MainActivity (правый щелчок мыши на папке menu | New | Menu Resource File ). Если вы будете создавать приложение с несколькими экранами, то у каждой активности будет отдельное меню со своими настройками. Пока откроем файл menu_main.xml и добавим в полученный шаблон свой код:

Откроем файл MainActivity . Сейчас в нём только один метод onCreate() . Добавим новый метод onCreateOptionsMenu() . Именно данный метод отвечает за появление меню у активности. Выберите в студии меню Code | и в следующим окне начинайте вводить название метода по первым буквам. Можно вводить по первым заглавным буквам, т.е. ocom (o nC reateO ptionsM enu), чтобы быстро найти нужную строку. Нажимаем кнопку OK и получаем заготовку.

@Override public boolean onCreateOptionsMenu(Menu menu) { return super.onCreateOptionsMenu(menu); }

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

@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; }

В методе inflate() вы указываете на ресурс меню (R.menu.menu_main ) и объект класса Menu .

По английски "inflate" переводится как надувать, т.е. по замыслу разработчиков Android, мы как бы надуваем данными объект, например, меню. Но на самом деле слово "inflate" происходит от словосочетания in flat - в квартиру. Существует старинная традиция запускать в квартиру первым кота, который исследует все закоулки дома и заявляет о своём согласии жить в нём. Так и мы запускаем данные из XML-файла в объект MenuInflater.

Запустите проект. Теперь в правой части заголовка вы увидите значок из трёх точек, выстроенных в вертикальную линию. Нажмите на значок, чтобы увидеть пункт меню 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() . Добавим метод по такому же принципу, как для предыдущего примера. Получим заготовку.

@Override public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); }

Параметр item отвечает за пункт меню. Вам следует получить идентификатор меню через метод getItemId() и указать для него код. Так как обычно меню состоит из нескольких пунктов, то удобно использовать конструкции if/else или switch . Для вывода информации воспользуемся текстовой меткой. Добавьте на экран активности компонент TextView . Можете использовать имеющийся TextView с надписью "Hello World!", только присвойте ему идентификатор.

android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!"/>

Добавим код в заготовку для выбранного пункта меню:

@Override public boolean onOptionsItemSelected(MenuItem item) { // получим идентификатор выбранного пункта меню int id = item.getItemId(); TextView infoTextView = (TextView) findViewById(R.id.textView); // Операции для выбранного пункта меню switch (id) { case R.id.action_cat1: infoTextView.setText("Вы выбрали кота!"); return true; case R.id.action_cat2: infoTextView.setText("Вы выбрали кошку!"); return true; case R.id.action_cat3: infoTextView.setText("Вы выбрали котёнка!"); return true; default: return super.onOptionsItemSelected(item); } }

Запустите приложение, вызовите меню и выберите любой пункт меню. В текстовом поле должно появиться сообщение.

Существует альтернативный способ через XML, похожий на обработку щелчков кнопки (начиная с Android 3.0). Вы можете добавить атрибут android:onClick в ресурсах меню, и вам не нужно использовать вызов метода onOptionsItemSelected() . При помощи android:onClick вы можете указать нужный метод при выборе пункта меню. Добавьте данный атрибут к пункту Settings

Теперь в коде активности напишем следующее:

// у атрибута пункта меню Settings установлено значение android:onClick="onSettingsMenuClick" public void onSettingsMenuClick(MenuItem item) { TextView infoTextView = (TextView) findViewById(R.id.textView); infoTextView.setText("Вы выбрали пункт Settings, лучше бы выбрали кота"); }

Переключатели

Внешний вид пунктов меню можно изменить на вид с переключателями. Для этого нужно добавить элемент group с атрибутом android:checkableBehavior="single" :

Большого смысла в этом режиме я не вижу. И рассматривать его не будем.

Режим Design

В Android Studio 2.2 добавили графический режим построения меню, которых похож на панель инструментов для добавления новых компонентов на экран. У меню панель состоит из четырёх элементов: Menu Item , Search Item , Menu , Group .

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

Итак, давайте сегодня создадим простое меню, для приложения на Android. Создадим новый проект. Назовем его Mymenu, нажмем next. Выберем Empty Activity. Нажмем finish.

Система Android studio подготовит нам новый проект, перейдем в gradle скрипы. В Build gradle, добавим новую имплементацию. Нам понадобятся пакет

implementation "com.android.support:design:26.0.0-beta1"

По крайней мере, в моем проекте. Нажмем синхронизировать проект.

Пункты меню

Перейдем в папку Res и создадим в ней новую Andriod ресурсную папку с ресурсным типом - меню. В ней же, создадим новый ресурс файл меню. Имя файлу присвоим, как и имя папки - menu.

На наше основное меню перетаскиванием, добавим MenuItem в количестве 3 штук.

В файле strings.xml напишем новые название, для пунктов меню, создав дополнительные строковые значение для них.

Пусть item1 будет Пункт 1, item2 Пункт 2, и item3 пусть будет Выход.

Пункт 1 Пункт 2 Выход

В текстовом варианте menu.xml присвоим названия из strings.xml для наших пунктов. Также для каждого item мы добавим, Android:id с именем action1, action2,action3,

для взаимодействия с данными пунктами. Действие номер 1 будет отвечать за что-то, какая то реакция, нажатие пункта Action 2, соответственно, будет отвечать за другие действие, Action 3 будет отвечать за выход из приложения.

В файле MainActivity напишем несколько функций для работы с меню:

onCreateOptionsMenu @Override public boolean onCreateOptionsMenu(Menu menu){ getMenuInflater().inflate(R.menu.menu, menu); return true; } onOptionsItemSelected @Override public boolean onOptionsItemSelected(MenuItem item){ int id = item.getItemId(); switch (id){ case R.id.action1: txt.setText(R.string.item1); return true; case R.id.action2: txt.setText(R.string.item2); return true; case R.id.action3: txt.setText(R.string.item3); finish(); return true; } return super.onOptionsItemSelected(item); }

Объявим переменную типа TextView txt, и свяжем ее с элементом TextView, в onCreate через

txt=(TextView)findViewById(R.id.txt),

в макете activity_main.xml, добавив ему

android:id="@+id/txt"

для отображения текста.

Запустим в эмуляторе наше приложение. Как видим, появляются пункты меню, при нажатии на значение Пункт 1 или 2, текст меняется на Пункт 1 или Пункт 2, при нажатии на кнопку Выход появляется текст Выход и приложение закрывается.

Верстка меню

Кажется, все хорошо. Однако, как всегда в Android Studio данное меню будет работать только на эмуляторе, и поэтому добавим в файл styles.xml небольшой код, а перед этим в AndroidManifest.xml изменим

android:theme="@style/AppTheme"

android:theme="@style/AppTheme.NoActionBar"

который говорит о том, что новый стиль без ActionBar. Также в MainActivity onCreate внесем переменную toolbar c типом ToolBar. Определим ее через toolbar = (Toolbar)findViewById(R.id.toolbar), и подключим поддержку setSupportActionBar(toolbar).

В макет activity_main.xml перед TextView добавим следующий код:

Подключим эти виджеты в импорт нашего приложения.

import android.support.v7.widget.Toolbar;

Нажмем Alt+Enter, и у нас добавится, обновится импорт нашего приложения. Возможно, придется сделать несколько раз для подключения виджета. Нажмем Сохранить.

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

Первого месяца обучения. Рассмотрим работу с меню глубже. Будут рассмотрены как старые устройства под Android 2.3, так и новые телефоны на Android 4.0.

Меню выбора опций (Options Menu)

За меню отвечает класс android.view.Menu . Каждая активность связана с одним объектом меню. Само меню содержит пункты меню (класс android.view.MenuItem ) и подменю (класс android.view.SubMenu ).

При нажатии кнопки Menu на старых телефонах появляется набор пунктов меню, прикрепляемый к активности. Меню может содержать значки. Такое меню может содержать шесть пунктов (как правило). При наличии более шести пунктов используется расширенное меню - в этом случае вместо шестого пункта появляется пункт Опции (More). При нажатии данного пункта показывается расширенное меню со списком пунктов, которые не поместились в основной части меню выбора опций.

Когда меню открывается впервые, Android вызывает метод onCreateOptionsMenu() , передавая в качестве параметра объект Menu . Меню можно создавать в виде ресурсов в XML-файле или использовать метод add() .

В стандартном проекте при выборе обычного шаблона уже есть заготовка для меню из одного пункта Settings и вызов метода для меню (вы об этом уже знаете).

Создание меню при помощи ресурсов

Рассмотрим работу с меню через ресурсы. Для создания меню используются ресурсы, которые должны храниться в XML-файле. Сам файл должен находиться в папке res/menu/ вашего проекта. Меню состоит из следующих элементов:

Определяет меню, которое будет содержать пункты меню. Элемент должен быть корневым элементом в XML-структуре файла и может содержать один или несколько элементов и Создает непосредственно пункты меню. Данный элемент может иметь вложенный элемент для создания подменю При желании можете также использовать невидимый контейнер для элементов . Это позволяет достичь некоторых эффектов

Предположим, мы решили использовать меню для какой-нибудь игры. Создадим новый файл game_menu.xml :

Мы создали меню с двумя пунктами. Каждый пункт включает в себя следующие атрибуты:

Android:id Идентификатор пункта меню, по которому приложение может распознать при выделении пункта меню пользователем android:title Текст, который будет выводиться в меню

Существуют и другие атрибуты для элемента item , например android:icon="@drawable/home" позволит также вывести значок для пункта меню, а android:enabled="false" позволяет сделать пункт меню недоступным.

Атрибут android:titleCondensed применяется в том случае, если обычный заголовок слишком широкий и не «помещается» в выбранном элементе меню.

Атрибут android:orderInCategory определяет порядок, в котором отображаются элементы меню MenuItems.

При создании меню мы указали на строковые ресурсы @string/new_game и @string/help . Необходимо добавить новые строки в файле strings.xml :

Новая игра Справка

Теперь нужно внести изменения в классе активности, в котором будет выводиться меню. Программа должна сконвертировать созданный нами ресурс меню в программный объект. Для этой цели существует специальный метод MenuInflater.inflate() , который вызывается в специальном методе обратного вызова onCreateOptionsMenu() . Данный метод и предназначен для вывода меню при нажатии кнопки MENU на устройстве:

@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.game_menu, menu); return true; }

После вставки кода среда разработки попросит импортировать недостающие пространства имен.

Import android.view.Menu; import android.view.MenuInflater;

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

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

Метод getMenuInflater() возвращает экземпляр класса MenuInflater , который мы используем для чтения данных меню из XML.

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

Сначала добавим шесть пунктов.

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

Выбор пунктов меню

Мы научились создавать меню. Но пока оно бесполезно, так как пункты меню никак не реагируют на наши нажатия. Для обработки нажатий пунктов меню служит метод onOptionsItemSelected() . Метод распознает пункт, выбранный пользователем, через MenuItem . Мы можем теперь определить выбранный пункт через вызов getItemId() , который возвращает идентификатор пункта меню. Далее через оператор switch нам остается определить нужные команды:

@Override public boolean onOptionsItemSelected(MenuItem item) { // Операции для выбранного пункта меню switch (item.getItemId()) { case R.id.new_game: newGame(); return true; case R.id.help: showHelp(); return true; default: return super.onOptionsItemSelected(item); } } public void newGame() { edtext.setText("Выбран пункт Новая игра"); } public void showHelp() { edtext.setText("Выбран пункт Справка"); }

Запустите приложение, вызовите меню и выберите первый или второй пункт меню. В текстовом поле должно появиться сообщение.

В приведенном примере getItemId() запрашивает ID для выбранного пункта меню и начинает сравнивать через оператор выбора switch с идентификаторами, которые мы задали в XML-ресурсах. При обнаружении нужного идентификатора выполняется обработчик для заданного пункта меню. Если программа ничего не обнаружит, то выполняется оператор default , который возвращает super class.

В Android 3.0 можно добавить атрибут android:onClick в ресурсах меню, и вам уже не нужно использовать onOptionsItemSelected() . При помощи android:onClick вы можете указать нужный метод при выборе пункта меню.

// у атрибута пункта меню установлено значение android:onClick="onMenuClick" public void onMenuClick(MenuItem item){ edtext.setText("Выбран пункт Накормить кота"); }

Программное создание меню

Рассмотрим программное создание меню для полноты картины. Нам понадобится определить несколько констант для пунктов меню:

// идентификаторы для пунктов меню private static final int IDM_OPEN = 101; private static final int IDM_SAVE = 102; public boolean onCreateOptionsMenu(Menu menu) { // добавляем пункты меню menu.add(Menu.NONE, IDM_OPEN, Menu.NONE, "Открыть"); menu.add(Menu.NONE, IDM_SAVE, Menu.NONE, "Сохранить"); }

У метода add() есть четыре параметра:

  • идентификатор группы - позволяет связывать пункт меню с группой других пунктов этого меню
  • идентификатор пункта для обработчика события выбора пункта меню
  • порядок расположения пункта в меню - позволяет определять позицию в меню. По умолчанию (Menu.NONE или 0) пункты идут в том порядке, как задано в коде
  • заголовок - текст, который выводится в пункте меню. Можно использовать строковый ресурс

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

Если вы хотите создать меню со значками, то воспользуйтесь методом setIcon()

Menu.add(Menu.NONE, IDM_OPEN, Menu.NONE, "Открыть") .setIcon(R.drawable.icon_menu_open);

Напомним еще раз, что значки можно добавить только к шести пунктам меню (или к пяти, если пунктов больше шести).

Метод onCreateOptionsMenu вызывается системой только один раз при создании меню. Если вам требуется обновить меню во время работы программы, то используйте метод обратного вызова onPrepareOptionsMenu() .

При выборе пункта меню вызывается метод onOptionsItemSelected , который передает объект MenuItem - пункт меню, выбранный пользователем. При помощи метода getItemId можно получить идентификатор выбранного пункта меню. После идентификации пункта меню можно написать код для обработки события выбора меню:

Public boolean onOptionsItemSelected(MenuItem item) { switсh (item.getItemId()) case IDM_OPEN: return true; case IDM_SAVE: return true; return false; }

Горячие клавиши

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

  • setAlphabeticShortcut(char) - добавляет символ
  • setNumericShortcut(int) - добавляет число
  • setShortcut(char, int) - добавляет комбинацию символа и числа

Например, если задать горячую клавишу setAlphabeticShortcut("q");, то при открытии меню (или при удерживании клавиши MENU) нажатие клавиши Q выберет данный пункт меню. Эта горячая клавиша (или сочетание клавиш) будет показана как подсказка, отображающая ниже имени пункта меню. В новых клавиатурах есть отдельная клавиша Ctrl , которая работает также, как на обычных клавиатурах.

Горячие клавиши можно создать и через XML: android:alphabeticShortcut="c" .

Обрабатывать нажатия можно через метод активности onKeyShortcut() :

@Override public boolean onKeyShortcut(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_R: Toast.makeText(this, "Reply", Toast.LENGTH_SHORT).show(); return true; default: return super.onKeyShortcut(keyCode, event); } }

Создание подменю

Подменю можно добавить в любое меню, кроме другого подменю. Подменю создается в методе обратного вызова onCreateOptionsMenu() с помощью метода addSubMenu() , который возвращает объект SubMenu . В объект SubMenu можно добавить дополнительные пункты к этому меню, используя метод add() . Например:

Public static final int IDM_HELP = 101; public static final int IDM_NEW = 201; public static final int IDM_OPEN = 202; public static final int IDM_SAVE = 203; public static final int IDM_CUT = 301; public static final int IDM_COPY = 302; public static final int IDM_PASTE = 303; @Override public boolean onCreateOptionsMenu(Menu menu) { SubMenu subMenuFile = menu.addSubMenu("Файл"); subMenuFile.add(Menu.NONE, IDM_NEW, Menu.NONE, "Новый"); subMenuFile.add(Menu.NONE, IDM_OPEN, Menu.NONE, "Открыть"); subMenuFile.add(Menu.NONE, IDM_SAVE, Menu.NONE, "Сохранить"); SubMenu subMenuEdit = menu.addSubMenu("Правка"); subMenuEdit.add(Menu.NONE, IDM_CUT, Menu.NONE, "Вырезать"); subMenuEdit.add(Menu.NONE, IDM_COPY, Menu.NONE, "Копировать"); subMenuEdit.add(Menu.NONE, IDM_PASTE, Menu.NONE, "Вставить"); menu.add(Menu.NONE, IDM_HELP, Menu.NONE, "Справка"); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { CharSequence message; switch (item.getItemId()) { case IDM_NEW: message = "Выбран пункт Новый"; break; case IDM_OPEN: message = "Выбран пункт Открыть"; break; case IDM_SAVE: message = "Выбран пункт Сохранить"; break; case IDM_CUT: message = "Выбран пункт Вырезать"; break; case IDM_COPY: message = "Выбран пункт Копировать"; break; case IDM_PASTE: message = "Выбран пункт Вставить"; break; case IDM_HELP: message = "Выбран пункт Справка"; break; default: return false; } // выводим уведомление о выбранном пункте меню Toast toast = Toast.makeText(this, message, Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return true; }

Теперь при выборе пункта меню появится еще одно окно с подменю. Попробуйте сами.

Добавление флажков и переключателей

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

MenuItem item = menu.add(0, IDM_FORMAT_BOLD, 0, "Bold"); item.setCheckable(true);

Если есть необходимость добавить несколько пунктов меню с флажками или переключателями, то можно объединить их в группы меню, создав отдельный идентификатор. Пункт меню добавляется в группу через метод add() , передав ему в качестве первого параметра идентификатор группы меню. Допустим, мы объявили идентификаторы для группы меню Цвет и элементов меню для установки цвета:

Public static final int IDM_COLOR_GROUP = 400; public static final int IDM_COLOR_RED = 401; public static final int IDM_COLOR_GREEN = 402; public static final int IDM_COLOR_BLUE = 403;

Теперь для создания группы меню с флажками нужно назначить идентификатор группы на каждый пункт меню и вызвать метод setGroupCheckable() для всей группы (этом случае нет необходимости вызывать метод setCheckable() для каждого пункта меню):

SubMenu subMenuColor = menu.addSubMenu("Цвет"); subMenuColor.add(IDM_COLOR_GROUP, IDM_COLOR_RED, Menu.NONE, "Красный"); subMenuColor.add(IDM_COLOR_GROUP, IDM_COLOR_GREEN, Menu.NONE,"Зеленый"); subMenuColor.add(IDM_COLOR_GROUP, IDM_COLOR_BLUE, Menu.NONE, "Синий"); subMenuColor.setGroupCheckable(IDM_COLOR_GROUP, true, false);

У метода setGroupCheckable() три параметра:

  • первый параметр - идентификатор группы меню;
  • второй параметр - true, если в группе разрешены переключатели или флажки;
  • третий параметр - устанавливает единственный (true) или множественный (false) выбор пунктов меню. Этот параметр фактически определяет внешний вид меню - это будет меню с переключателями или флажками.

    Для управления состоянием флажков и переключателей в обработчике события выбора пункта меню нужно написать следующее:

    @Override public boolean onOptionsItemSelected(MenuItem item) { CharSequence message; switch (item.getItemId()) { ... case IDM_COLOR_RED: // инвертируем состояние флажка item.setChecked(!item.isChecked()); message = "Красный цвет"; break; default: return false; }

    Запустите проект, вызовите меню и выберите пункт меню Цвет . У вас появится подменю с тремя пунктами (Красный, Зеленый, Синий) в виде флажков. Состояние флажков и переключателей обрабатывается в коде программы и сохраняется при повторных вызовах меню.

    Можно сразу назначить намерение выбранному пункту меню через метод setIntent(), которое сработает при нажатии этого пункта, если данное событие не было перехвачено обработчиками onMenuItemClickListener (устар.) или onOptionsItemSelected. Сработав, намерение передается в метод startActivity.

    MenuItem.setIntent(new Intent(this, MyOtherActivity.class));

    Программное открытие или закрытие меню

    Если вам по каким-то причинам нужно программно открыть меню (например, в демонстрационных целях), то используйте метод openOptionsMenu() :

    OpenOptionsMenu();

    Для программного закрытия меню используйте метод closeOptionsMenu() , впрочем у меня повторный вызов метода openOptionsMenu() также закрывает меню.

    Программное удаление пункта меню

    Допустим, мы определили пункт меню в xml-файле:

    Чтобы удалить явно лишний пункт меню из нашей программы о котах, нужно получить доступ к пункту меню через метод findItem() и сделать его невидимым. Ссылку на объект Menu нужно передать в метод onCreateOptionsMenu , чтобы программа узнала об изменении состава меню.

    // переменная класса Menu menu; @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // передаём ссылку на наш объект this.menu = menu; getMenuInflater().inflate(R.menu.test, menu); return true; } // щелчок кнопки public void onClick(View v) { if (menu != null) { // находим нужный элемент MenuItem item_dog = menu.findItem(R.id.action_dog); // делаем его невидимым item_dog.setVisible(false); } }

    Но у данного решения есть недостаток, если мы повернём экран, то активность пересоздатся и удалённое меню снова появится. Как же нам избавиться от сранного пёсика?

    Надо запомнить состояние пункта меню и сохранить его в объекте типа Bundle в методе onSaveInstanceState , а в методе onCreate() извлечь сохранённое состояние и передать методу onPrepareOptionsMenu , который вызывается перед показом меню на экране:

    Package ru.alexanderklimov.test; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class TestActivity extends Activity { Menu menu; Boolean savedMenuDogIsVisible; final static String KEY_MENU_DOG = "KEY_MENU_DOG"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); // извлекаем данные о видимости пункта меню if (savedInstanceState != null) { savedMenuDogIsVisible = savedInstanceState.getBoolean(KEY_MENU_DOG, true); } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); this.menu = menu; getMenuInflater().inflate(R.menu.test, menu); return true; } public void onClick(View v) { if (menu != null) { MenuItem item_dog = menu.findItem(R.id.action_dog); // прячем пункт меню item_dog.setVisible(false); } } @Override protected void onSaveInstanceState(Bundle outState) { // TODO Auto-generated method stub super.onSaveInstanceState(outState); if (menu != null) { MenuItem item_dog = menu.findItem(R.id.action_dog); // сохраняем текущее состояние пункта меню - true или false outState.putBoolean(KEY_MENU_DOG, item_dog.isVisible()); } } @Override public boolean onPrepareOptionsMenu(Menu menu) { if (savedMenuDogIsVisible != null) { MenuItem item_dog = menu.findItem(R.id.action_dog); // перед выводом на экран узнаём нужное состоятние пункта меню item_dog.setVisible(savedMenuDogIsVisible); } return super.onPrepareOptionsMenu(menu); } }

    Определить наличие кнопки Menu

    На старых устройствах использовалась реальная кнопка Menu. В новых версиях Android меню убрали в ActionBar и её наличие в виде отдельной кнопки стало необязательным. Но многие производители по-прежнему выпускают телефоны с кнопкой для меню. Чтобы определить, есть ли такая кнопка, в Android 14 добавили новый метод, который позволит определить наличие этой кнопки.

    If (Build.VERSION.SDK_INT <= 10 || (Build.VERSION.SDK_INT >= 14 && ViewConfiguration.get(this) .hasPermanentMenuKey())) { // menu key is present Toast.makeText(this, "Кнопка Menu есть", Toast.LENGTH_LONG).show(); } else { // No menu key Toast.makeText(this, "Кнопки Menu нет", Toast.LENGTH_LONG).show(); }

    Разметка для меню

    В современных устройствах меню является частью ActionBar . И вы можете настроить разметку меню через XML.

    Допустим, вы выбрали такой вариант:

    В атрибуте showAsAction не используйте значение never , иначе разметку не увидите. Сама разметка задана через атрибут actionLayout . Код для разметки:

    Меню в фрагментах

    Меню может быть не только частью активности, но и частью фрагмента. Принцип работы практически не отличается. У фрагмента есть соответствующий метод.

    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.fragment_crime_list, menu); }

    FragmentManager отвечает за вызов onCreateOptionsMenu() при получении активностью обратного вызова onCreateOptionsMenu() от системы. Вы должны явно сообщить менеджеру FragmentManager , что фрагмент должен получить вызов onCreateOptionsMenu() . Для этого вызывается метод setHasOptionsMenu() :

    // В коде фрагмента @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); getActivity().setTitle(R.string.cat); ... }

При длительном нажатии на кнопку питания смартфона или планшета мы, как правило, вызываем меню выключения с двумя опциями: «Выключить» и «Перезагрузить». По большому счету обычному пользователю этого вполне достаточно, и менять что-либо он не будет. Другое дело – продвинутые пользователи, которые не понаслышке знают, что такое Recovery Mode, Bootloader, «мягкая перезагрузка» и были бы не против расширить скудное меню этими функциями. В статье мы расскажем, как это сделать.

Что можно добавить в меню выключения Android

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

Опытные пользователи мобильных устройств на Android хоть раз в своей жизни перепрошивали свои гаджеты. При этом очень часто они используют специальный режим загрузки Android – Recovery Mode. Он позволяет не только прошить аппарат, но и сделать полный сброс системы до заводских настроек, создать резервную копию, очистить память телефона, получить ROOT и многое другое. Для входа в этот режим обычно используются комбинации нажатий кнопок устройства. Причем для каждой марки смартфона или планшета они могут быть разными. Чтобы не задаваться этим вопросом и каждый раз не нажимать обозначенные кнопки, этот параметр можно добавить в меню выключения.


Мы рассмотрим несколько вариантов изменения системного меню выключения с помощью модуля для Xposed и приложений Material Power Menu и Quick Reboot. Для корректной работы все они требуют наличия на устройстве .

Внимание! Действия, описанные в этой статье, вы совершаете на свой страх и риск. Если вы не совсем понимаете, зачем вам это нужно, лучше ничего не делайте. Редакция сайта Трешбокс не несет ответственности за «окирпичивание» ваших устройств.

Модуль Advanced Power Menu для Xposed

Преимуществом данного способа является то, что все изменения интегрируются непосредственно в системное меню выключения Android. Для изменения параметров выключения устройства вам понадобится специальная среда выполнения . Откройте приложение , перейдите в репозиторий и найдите там Advanced Power Menu (APM+) . Установите модуль и не забудьте активировать его в настройках Xposed. Перезагрузите устройство.



APM+ очень прост в использовании. При первом запуске вы увидите пункты системного меню выключения. Здесь можно удалять имеющиеся пункты, создавать новые и менять их расположение путем перетаскивания. Для некоторых опций утилита позволяет настраивать расширенные параметры в пределах каждого пункта меню. Например, по нажатию на «Перезагрузить» система предложит выбрать тип перезагрузки: обычная, «мягкая», Recovery Mode и Bootloader.





С помощью APM+ можно добавить в меню фонарик, Wi-Fi, звуковые профили, режимы мобильной сети, передачу данных, скриншот, быстрый набор номера и запись экрана. В дополнение к этому внешний вид самого меню также можно незначительно украсить, применив одну из тем оформления.




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






Advanced Power Menu лучше всего подходит для устройств со стоковым Android 4.0 и выше. На многих фирменных оболочках модуль не работает, разработчиком заявлена поддержка только Xperia UI и TouchWiz. Сейчас, по всей видимости, работа над модулем приостановлена. Утилита уже более года как не получала обновление, а ее последняя версия лишь частично поддерживает Android 6.0. Тем не менее, если у вас есть аппарат на KitKat или Lollipop – можете попробовать поставить на него APM+.


Как известно, Android KitKat содержит более расширенное меню выключения, нежели Lollipop и Marshmallow. В нем, кроме пунктов «Выключить» и «Перезагрузить» есть еще «Режим полета» и звуковые профили. Приложение Material Power Menu возвращает их в меню на устройствах с Android 5.0 и выше. В качестве бонуса утилита содержит опции для входа в режим загрузчика и восстановления, а также «мягкую» перезагрузку, при которой перезапускается только интерфейс системы. Еще одной интересной функцией программы является Safe Mode (безопасный режим). В этом режиме, по аналогии с компьютером, система Android загружается с отключенными сторонними приложениями. Если вы, например, подхватили какой-нибудь троян или другой зловред, можно использовать Safe Mode для его удаления из системы.

Material Power Menu работает независимо от механической кнопки питания устройства. Для удобства вызова меню выключения можно вынести ярлык приложения на рабочий стол. Таким образом, утилита окажется полезной в случае, если у вас сломалась кнопка питания. При наличии ROOT и Xposed, Material Power Menu интегрируется в среду в качестве программного модуля и полностью заменяет системное меню выключения Android. Правда включается это меню не совсем удобно – повторным долгим нажатием на кнопку питания. Но на некоторых прошивках это может не сработать.

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


В отличие от предыдущих решений, данный способ с использованием приложения Quick Reboot не предусматривает каких-либо изменений в системном меню выключения Android. Quick Reboot – это довольно простая утилита, задача которой заменить собой кнопку питания устройства. То есть вы можете выключать свой смартфон или планшет по старинке (с помощью кнопки питания), либо через это приложение. Кроме основных параметров меню выключения, программа позволяет перезагрузиться в режим восстановления или загрузчика без запоминания комбинаций клавиш. Для удобства запуска команд Quick Reboot имеет виджеты.




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

В итоге

Подводя итоги, можно выделить два основных момента, при которых подобные утилиты могут пригодиться. Первый – когда вы хотите модифицировать системное меню выключения Android и расширить его функциональные возможности необходимыми вам опциями. В этом случае советуем попробовать Xposed-модуль Advanced Power Menu с отличным набором функций.

Второй – это тот момент, когда у вас не работает кнопка питания или громкости (для комбинации, чтобы войти в режим загрузчика или восстановления) или наблюдаются проблемы с их нажатием. В этой ситуации такие приложения, как Material Power Menu и Quick Reboot придутся как нельзя кстати.