Меню в приложениях представляет класс android.view.Menu, и каждая activity ассоциируется с объектом этого типа. Объект android.view.Menu может включать различное количество элементов, а те в свою очередь могут хранить подэлементы.
Меню, как и файлы интерфейса или изображений, также представляет собой ресурс. Однако при создании нового проекта с Empty Activity по умолчанию нет никаких ресурсов меню, поэтому при необходимости их нужно добавлять вручную. Так, для определения ресурсов меню в проекте нажмем правой кнопкой мыши в проекте на каталог res и далее в открывшемся списоке выберем пункт New -> Android Resource File:
Далее в появившемся окне укажем для имени файла название main_menu, а для поля Resource Type (тип ресурса) выберем Menu:
После этого в каталоге res будет создан подкаталог menu, в котором будет находиться файл main_menu.xml.
По умолчанию этот файл определяет один пустой элемент menu:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> </menu>
Изменим содержимое файла, определив несколько пунктов:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_settings" android:orderInCategory="1" android:title="Настройки" /> <item android:id="@+id/save_settings" android:orderInCategory="3" android:title="Сохранить" /> <item android:id="@+id/open_settings" android:orderInCategory="2" android:title="Открыть" /> </menu>
Тег <menu>
является корневым узлом файла и определяет меню, состоящее из одного или нескольких элементов
<item>
и <group>
.
Элемент <item>
представляет объект MenuItem, которой является одним из элементов меню.
Этот элемент может содержать внутренний подэлемент <menu>
, с помощью которого создается подменю.
Элемент <item>
включает следующие атрибуты, которые определяют его внешний вид и поведение:
android:id: уникальный id элемента меню, который позволяет его опознать при выборе пользователем и найти через поиск ресурса по id
android:icon: ссылка на ресурс drawable, который задает изображение для элемента (android:icon="@drawable/ic_help"
)
android:title: ссылка на ресурс строки, содержащий заголовок элемента. По умолчанию имеет значение "Settings"
android:orderInCategory: порядок следования элемента в меню
Мы определили меню с тремя элементами, но само определение элементов в файле еще не создает меню. Это всего лишь декларативное описание. Чтобы вывести его на экран, нам надо использовать его в классе Activity. Для этого надо переопределить метод onCreateOptionsMenu. Итак, перейдем к классу MainActivity и изменим его следующим образом:
package com.example.menuapp; import androidx.appcompat.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:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/selectedMenuItem" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" android:textSize="28sp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
И изменим класс MainActivity:
package com.example.menuapp; import androidx.appcompat.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 = findViewById(R.id.selectedMenuItem); 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; } //headerView.setText(item.getTitle()); return super.onOptionsItemSelected(item); } }
Чтобы понять, какой пункт меню выбран, вначале получаем его идентификатор int id = item.getItemId()
. Затем пробегаемся в
конструкции switch..case и выбираем нужный вариант и в зависимости от выбора производим определенные действия - в данном случае устанавливаем текст
TextView.
Стоит отметить, что в данном случае, если наша задача заключалась, чтобы просто в выводе текста выбранного пункта меню, то мы вместо конструкции switch просто могли написать так:
headerView.setText(item.getTitle());
Кроме определения элементов меню в xml, можно также создать меню программным способом. Для добавления новых пунктов меню используется метод add() класса Menu.
Например, изменим код MainActivity:
package com.example.menuapp; import androidx.appcompat.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) { super.onCreateOptionsMenu(menu); menu.add("Настройки"); menu.add("Открыть"); menu.add("Сохранить"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { String title = item.getTitle().toString(); TextView headerView = findViewById(R.id.selectedMenuItem); headerView.setText(title); return super.onOptionsItemSelected(item); } }
Использованная версия метода add()
принимает заголовок для пункта меню.