Створення меню

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

Визначення меню в xml

Меню, як і файли інтерфейсу чи зображення, також є ресурсом. Однак при створенні нового проекту з типом 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> в Android

Тег <menu> є кореневим елементом файлу і визначає меню, яке складається з одного або кількох елементів <item> та <group>.

Елемент <item>

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