Меню в приложениях представляет класс 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() принимает заголовок для пункта меню.