Speisekarten hinzufügen

Compose ausprobieren
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Weitere Informationen zum Hinzufügen von Komponenten in Compose

Menüs sind eine gängige Benutzeroberflächenkomponente in vielen Arten von Apps. Verwenden Sie die Menu APIs, um Nutzeraktionen und andere Optionen in Ihren Aktivitäten zu präsentieren und so eine vertraute und einheitliche Nutzererfahrung zu bieten.

Ein Bild, das ein Beispiel für ein Drop-down-Menü zeigt
Abbildung 1. Ein Menü, das durch Tippen auf ein Symbol ausgelöst wird und unter dem Symbol für das Dreipunkt-Menü angezeigt wird.

In diesem Dokument wird gezeigt, wie Sie die drei grundlegenden Arten von Menüs oder Aktionsdarstellungen in allen Android-Versionen erstellen:

Optionsmenü und App-Leiste
Das Optionsmenü enthält die wichtigsten Menüpunkte für eine Aktivität. Hier platzieren Sie Aktionen, die sich global auf die App auswirken, z. B. „Suchen“, „E-Mail schreiben“ und „Einstellungen“.

Weitere Informationen finden Sie im Abschnitt Optionsmenü erstellen.

Kontextmenü und Kontext-Aktionsbanner
Ein Kontextmenü ist ein schwebendes Menü, das angezeigt wird, wenn der Nutzer ein Element gedrückt hält. Es bietet Aktionen, die sich auf den ausgewählten Inhalt oder Kontextbereich auswirken.

Im Kontextaktionsmodus werden Aktionselemente, die sich auf die ausgewählten Inhalte auswirken, in einer Leiste oben auf dem Bildschirm angezeigt. Der Nutzer kann mehrere Elemente auswählen.

Weitere Informationen finden Sie im Abschnitt Kontextmenü erstellen.

Pop-up-Menü
Ein Pop-up-Menü enthält eine vertikale Liste von Elementen, die an der Ansicht verankert ist, über die das Menü aufgerufen wird. Sie eignet sich gut, um eine Reihe von Aktionen für bestimmte Inhalte bereitzustellen oder Optionen für den zweiten Teil eines Befehls anzugeben. Aktionen in einem Pop-up-Menü wirken sich nicht direkt auf die entsprechenden Inhalte aus. Dafür sind kontextbezogene Aktionen gedacht. Das Pop-up-Menü enthält erweiterte Aktionen, die sich auf Inhaltsbereiche in Ihren Aktivitäten beziehen.

Weitere Informationen finden Sie im Abschnitt Pop-up-Menü erstellen.

Menü in XML definieren

Für alle Menütypen bietet Android ein Standard-XML-Format zum Definieren von Menüpunkten. Anstatt ein Menü im Code Ihrer Aktivität zu erstellen, definieren Sie ein Menü und alle seine Elemente in einer XML-Menüressource. Sie können die Menüressource dann in Ihrer Aktivität oder Ihrem Fragment als Menu-Objekt laden.

Die Verwendung einer Menüressource ist aus folgenden Gründen empfehlenswert:

  • Die Menüstruktur lässt sich in XML leichter visualisieren.
  • So werden die Inhalte des Menüs vom Verhaltenscode Ihrer App getrennt.
  • Sie können alternative Menükonfigurationen für verschiedene Plattformversionen, Bildschirmgrößen und andere Konfigurationen erstellen, indem Sie das Framework App-Ressourcen verwenden.

Wenn Sie ein Menü definieren möchten, erstellen Sie eine XML-Datei im Verzeichnis res/menu/ Ihres Projekts und erstellen Sie das Menü mit den folgenden Elementen:

<menu>
Definiert einen Menu, einen Container für Menüpunkte. Ein <menu>-Element muss der Stammknoten der Datei sein und kann ein oder mehrere <item>- und <group>-Elemente enthalten.
<item>
Erstellt eine MenuItem, die ein einzelnes Element in einem Menü darstellt. Dieses Element kann ein verschachteltes <menu>-Element enthalten, um ein Untermenü zu erstellen.
<group>
Optionaler, unsichtbarer Container für <item>-Elemente. Sie können Menüpunkte so kategorisieren, dass sie gemeinsame Eigenschaften wie den aktiven Status und die Sichtbarkeit haben. Weitere Informationen finden Sie im Abschnitt Menügruppe erstellen.

Hier ein Beispiel für ein Menü namens game_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/new_game"
          android:icon="@drawable/ic_new_game"
          android:title="@string/new_game"
          app:showAsAction="ifRoom"/>
    <item android:id="@+id/help"
          android:icon="@drawable/ic_help"
          android:title="@string/help" />
</menu>

Das Element <item> unterstützt mehrere Attribute, mit denen Sie das Aussehen und Verhalten eines Elements definieren können. Die Elemente im vorherigen Menü haben die folgenden Attribute:

android:id
Eine eindeutige Ressourcen-ID für das Element, anhand derer die App das Element erkennt, wenn der Nutzer es auswählt.
android:icon
Eine Referenz auf ein drawable, das als Symbol des Elements verwendet werden soll.
android:title
Ein Verweis auf einen String, der als Titel des Artikels verwendet werden soll.
android:showAsAction
Die Angabe, wann und wie dieses Element als Aktionselement in der App-Leiste angezeigt wird.

Dies sind die wichtigsten Attribute, die Sie verwenden. Es gibt jedoch noch viele weitere. Informationen zu allen unterstützten Attributen finden Sie in der Dokumentation zur Menüressource.

Sie können einem Element in einem beliebigen Menü ein Untermenü hinzufügen, indem Sie ein <menu>-Element als untergeordnetes Element eines <item> hinzufügen. Untermenüs sind nützlich, wenn Ihre App viele Funktionen hat, die nach Themen organisiert werden können, z. B. Elemente in der Menüleiste einer PC-Anwendung wie Datei, Bearbeiten und Ansicht. Sehen Sie sich folgendes Beispiel an:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/file"
          android:title="@string/file" >
        <!-- "file" submenu -->
        <menu>
            <item android:id="@+id/create_new"
                  android:title="@string/create_new" />
            <item android:id="@+id/open"
                  android:title="@string/open" />
        </menu>
    </item>
</menu>

Wenn Sie das Menü in Ihrer Aktivität verwenden möchten, müssen Sie die Menüressource _aufblähen_, indem Sie die XML-Ressource mit MenuInflater.inflate() in ein programmierbares Objekt konvertieren. In den folgenden Abschnitten wird beschrieben, wie Sie ein Menü für jeden Menütyp maximieren.

Optionsmenü erstellen

Im Optionsmenü, wie in Abbildung 1 dargestellt, fügen Sie Aktionen und andere Optionen hinzu, die für den aktuellen Aktivitätskontext relevant sind, z. B. „Suchen“, „E-Mail schreiben“ und „Einstellungen“.

Ein Bild, das die App-Leiste der Google Tabellen App zeigt
Abbildung 2. Die Google Tabellen App mit mehreren Schaltflächen, darunter die Schaltfläche „Dreipunkt-Menü“.

Sie können Elemente für das Optionsmenü aus Ihrer Activity-Unterklasse oder einer Fragment-Unterklasse deklarieren. Wenn sowohl Ihre Aktivität als auch Ihre Fragmente Elemente für das Optionsmenü angeben, werden die Elemente in der Benutzeroberfläche kombiniert. Die Elemente der Aktivität werden zuerst angezeigt, gefolgt von den Elementen der einzelnen Fragmente in der Reihenfolge, in der sie der Aktivität hinzugefügt werden. Bei Bedarf können Sie die Menüpunkte mit dem Attribut android:orderInCategory in jeder <item> neu anordnen, die Sie verschieben möchten.

Wenn Sie das Optionsmenü für eine Aktivität angeben möchten, überschreiben Sie onCreateOptionsMenu(). Fragmente haben einen eigenen onCreateOptionsMenu()-Callback. Bei dieser Methode kannst du deine in XML definierte Menüressource in die im Rückruf bereitgestellte Menu einfügen. Das ist im folgenden Beispiel zu sehen:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    val inflater: MenuInflater = menuInflater
    inflater.inflate(R.menu.game_menu, menu)
    return true
}

Java

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

Sie können Menüpunkte auch mit add() hinzufügen und Elemente mit findItem() abrufen, um ihre Properties mit MenuItem APIs zu überarbeiten.

Click-Events verarbeiten

Wenn der Nutzer ein Element aus dem Optionsmenü auswählt, einschließlich Aktionselementen in der App-Leiste, ruft das System die Methode onOptionsItemSelected() Ihrer Aktivität auf. Diese Methode übergibt die ausgewählte MenuItem. Sie können den Artikel identifizieren, indem Sie getItemId() aufrufen. Dadurch wird die eindeutige ID für den Menüpunkt zurückgegeben, die durch das Attribut android:id in der Menüressource oder durch eine Ganzzahl definiert wird, die der Methode add() übergeben wird. Sie können diese ID mit bekannten Menüpunkten abgleichen, um die entsprechende Aktion auszuführen.

Kotlin

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    // Handle item selection.
    return when (item.itemId) {
        R.id.new_game -> {
            newGame()
            true
        }
        R.id.help -> {
            showHelp()
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Java

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection.
    switch (item.getItemId()) {
        case R.id.new_game:
            newGame();
            return true;
        case R.id.help:
            showHelp();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Wenn du einen Menüpunkt erfolgreich verarbeitet hast, gib true zurück. Wenn Sie den Menüpunkt nicht verarbeiten, rufen Sie die Superklasseimplementierung von onOptionsItemSelected() auf. Die Standardimplementierung gibt „false“ zurück.

Wenn Ihre Aktivität Fragmente enthält, ruft das System zuerst onOptionsItemSelected() für die Aktivität und dann für jedes Fragment in der Reihenfolge auf, in der die Fragmente hinzugefügt wurden, bis eines true zurückgibt oder alle Fragmente aufgerufen wurden.

Menüpunkte zur Laufzeit ändern

Nachdem das System onCreateOptionsMenu() aufgerufen hat, behält es eine Instanz der von Ihnen ausgefüllten Menu bei und ruft onCreateOptionsMenu() nur dann noch einmal auf, wenn das Menü ungültig wird. Verwenden Sie onCreateOptionsMenu() jedoch nur, um den ursprünglichen Menüstatus zu erstellen, und nicht, um während des Aktivitätszyklus Änderungen vorzunehmen.

Wenn Sie das Optionsmenü basierend auf Ereignissen ändern möchten, die während des Aktivitätszyklus auftreten, können Sie dies in der Methode onPrepareOptionsMenu() tun. Bei dieser Methode wird das Menu-Objekt in seiner aktuellen Form übergeben, damit Sie es ändern können, z. B. indem Sie Elemente hinzufügen, entfernen oder deaktivieren. Fragmente bieten auch einen onPrepareOptionsMenu()-Callback.

Das Optionsmenü gilt als immer geöffnet, wenn Menüpunkte in der App-Leiste angezeigt werden. Wenn ein Ereignis eintritt und du ein Menü aktualisieren möchtest, rufe invalidateOptionsMenu() auf, um zu beantragen, dass das System onPrepareOptionsMenu() aufruft.

Kontextmenü erstellen

Ein Bild mit einem schwebenden Kontextmenü
Abbildung 3. Ein schwebendes Kontextmenü.

Ein Kontextmenü bietet Aktionen, die sich auf ein bestimmtes Element oder einen bestimmten Kontextrahmen in der Benutzeroberfläche auswirken. Sie können ein Kontextmenü für jede Ansicht bereitstellen. Am häufigsten werden sie jedoch für Elemente in einer RecylerView oder anderen Ansichtssammlung verwendet, in der Nutzer direkte Aktionen auf jedes Element ausführen können.

Es gibt zwei Möglichkeiten, kontextbezogene Aktionen bereitzustellen:

  • In einem schwebenden Kontextmenü Ein Menü wird als schwebende Liste von Menüpunkten angezeigt, ähnlich wie ein Dialogfeld, wenn der Nutzer eine Ansicht gedrückt hält, die die Unterstützung eines Kontextmenüs angibt. Nutzer können eine kontextbezogene Aktion jeweils nur auf ein Element ausführen.
  • Im Kontext-Aktionsbanner Dieser Modus ist eine Systemimplementierung von ActionMode. Oben auf dem Bildschirm wird eine Kontextaktionsleiste(Contextual Action Bar, CAB) mit Aktionselementen angezeigt, die sich auf die ausgewählten Elemente auswirken. Wenn dieser Modus aktiv ist, können Nutzer eine Aktion auf mehrere Elemente gleichzeitig ausführen, sofern Ihre App dies unterstützt.

Hinweis:Das Kontextmenü unterstützt keine Tastenkürzel und Symbole für Elemente.

Ein schwebendes Kontextmenü erstellen

So fügen Sie ein schwebendes Kontextmenü hinzu:

  1. Registrieren Sie die View, die dem Kontextmenü zugeordnet ist, indem Sie registerForContextMenu() aufrufen und die View übergeben.

    Wenn in Ihrer Aktivität eine RecyclerView verwendet wird und jedes Element dasselbe Kontextmenü enthalten soll, registrieren Sie alle Elemente für ein Kontextmenü, indem Sie die RecyclerView an registerForContextMenu() übergeben.

  2. Implementieren Sie die Methode onCreateContextMenu() in Activity oder Fragment.

    Wenn die registrierte Ansicht ein Ereignis vom Typ „Berühren und halten“ empfängt, ruft das System die Methode onCreateContextMenu() auf. Hier definieren Sie die Menüpunkte, in der Regel durch Aufblasen einer Menüressource, wie im folgenden Beispiel:

    Kotlin

        override fun onCreateContextMenu(menu: ContextMenu, v: View,
                                menuInfo: ContextMenu.ContextMenuInfo) {
            super.onCreateContextMenu(menu, v, menuInfo)
            val inflater: MenuInflater = menuInflater
            inflater.inflate(R.menu.context_menu, menu)
        }
        

    Java

        @Override
        public void onCreateContextMenu(ContextMenu menu, View v,
                                        ContextMenuInfo menuInfo) {
            super.onCreateContextMenu(menu, v, menuInfo);
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.context_menu, menu);
        }
        

    Mit MenuInflater lassen sich Kontextmenüs aus einer Menüressource aufblähen. Die Parameter der Callback-Methode umfassen die vom Nutzer ausgewählte View und ein ContextMenu.ContextMenuInfo-Objekt mit zusätzlichen Informationen zum ausgewählten Element. Wenn Ihre Aktivität mehrere Ansichten hat, die jeweils ein anderes Kontextmenü enthalten, können Sie mithilfe dieser Parameter festlegen, welches Kontextmenü maximiert werden soll.

  3. Implementieren Sie onContextItemSelected() wie im folgenden Beispiel gezeigt. Wenn der Nutzer einen Menüpunkt auswählt, ruft das System diese Methode auf, damit Sie die entsprechende Aktion ausführen können.

    Kotlin

        override fun onContextItemSelected(item: MenuItem): Boolean {
            val info = item.menuInfo as AdapterView.AdapterContextMenuInfo
            return when (item.itemId) {
                R.id.edit -> {
                    editNote(info.id)
                    true
                }
                R.id.delete -> {
                    deleteNote(info.id)
                    true
                }
                else -> super.onContextItemSelected(item)
            }
        }
        

    Java

        @Override
        public boolean onContextItemSelected(MenuItem item) {
            AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
            switch (item.getItemId()) {
                case R.id.edit:
                    editNote(info.id);
                    return true;
                case R.id.delete:
                    deleteNote(info.id);
                    return true;
                default:
                    return super.onContextItemSelected(item);
            }
        }
        

    Die Methode getItemId() fragt die ID für den ausgewählten Menüpunkt ab, die Sie jedem Menüpunkt in XML mit dem android:id-Attribut zuweisen, wie im Abschnitt Menü in XML definieren beschrieben.

    Wenn du einen Menüpunkt erfolgreich verarbeitet hast, gib true zurück. Wenn Sie den Menüpunkt nicht verarbeiten, übergeben Sie ihn an die Implementierung der Superklasse. Wenn Ihre Aktivität Fragmente enthält, wird dieser Rückruf zuerst an die Aktivität gesendet. Wenn die Superklasse bei nicht gehandhabten Ereignissen aufgerufen wird, übergibt das System das Ereignis nacheinander in der Reihenfolge, in der die einzelnen Fragmente hinzugefügt wurden, an die jeweilige Rückrufmethode in jedem Fragment, bis true oder false zurückgegeben wird. Die Standardimplementierungen für Activity und android.app.Fragment geben false zurück. Rufen Sie daher bei nicht verarbeiteten Ereignissen immer die Superklasse auf.

Kontext-Aktionsbanner verwenden

Der Modus für kontextbezogene Aktionen ist eine Systemimplementierung von ActionMode, bei der die Nutzerinteraktion auf die Ausführung kontextbezogener Aktionen ausgerichtet ist. Wenn ein Nutzer diesen Modus durch Auswählen eines Elements aktiviert, wird oben auf dem Bildschirm eine Kontextaktionsleiste angezeigt, in der Aktionen aufgeführt sind, die der Nutzer auf die ausgewählten Elemente ausführen kann. Wenn dieser Modus aktiviert ist, kann der Nutzer mehrere Elemente auswählen, sofern Ihre App dies unterstützt. Er kann die Auswahl von Elementen aufheben und sich weiter in der Aktivität bewegen. Der Aktionsmodus wird deaktiviert und die kontextbezogene Aktionsleiste verschwindet, wenn der Nutzer die Auswahl aller Elemente aufhebt, auf die Schaltfläche „Zurück“ tippt oder links in der Leiste auf Fertig tippt.

Bei Ansichten mit kontextabhängigen Aktionen wird der Modus für kontextabhängige Aktionen in der Regel aufgerufen, wenn eines oder beide dieser beiden Ereignisse auftreten:

  • Der Nutzer hält die Ansicht gedrückt.
  • Der Nutzer wählt in der Ansicht ein Kästchen oder eine ähnliche UI-Komponente aus.

Wie Ihre App den Modus für kontextbezogene Aktionen aufruft und das Verhalten für jede Aktion definiert, hängt von Ihrem Design ab. Es gibt zwei Designs:

  • Für kontextbezogene Aktionen auf einzelnen, beliebigen Ansichten.
  • Für Batch-Kontextaktionen auf Gruppen von Elementen in einer RecyclerView, mit denen Nutzer mehrere Elemente auswählen und eine Aktion auf alle ausführen können.

In den folgenden Abschnitten wird die für das erste Szenario erforderliche Einrichtung beschrieben.

Kontext-Aktionsbanner für einzelne Aufrufe aktivieren

Wenn der Kontext-Aktionsbanner nur dann angezeigt werden soll, wenn der Nutzer bestimmte Ansichten auswählt, gehen Sie so vor:

  1. Implementieren Sie die ActionMode.Callback-Benutzeroberfläche wie im folgenden Beispiel gezeigt. In den Rückrufmethoden können Sie die Aktionen für die kontextbezogene Aktionsleiste angeben, auf Klickereignisse auf Aktionselemente reagieren und andere Lebenszyklusereignisse für den Aktionsmodus verarbeiten.

    Kotlin

        private val actionModeCallback = object : ActionMode.Callback {
            // Called when the action mode is created. startActionMode() is called.
            override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
                // Inflate a menu resource providing context menu items.
                val inflater: MenuInflater = mode.menuInflater
                inflater.inflate(R.menu.context_menu, menu)
                return true
            }
    
            // Called each time the action mode is shown. Always called after
            // onCreateActionMode, and might be called multiple times if the mode
            // is invalidated.
            override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
                return false // Return false if nothing is done
            }
    
            // Called when the user selects a contextual menu item.
            override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
                return when (item.itemId) {
                    R.id.menu_share -> {
                        shareCurrentItem()
                        mode.finish() // Action picked, so close the CAB.
                        true
                    }
                    else -> false
                }
            }
    
            // Called when the user exits the action mode.
            override fun onDestroyActionMode(mode: ActionMode) {
                actionMode = null
            }
        }
        

    Java

        private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
    
            // Called when the action mode is created. startActionMode() is called.
            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                // Inflate a menu resource providing context menu items.
                MenuInflater inflater = mode.getMenuInflater();
                inflater.inflate(R.menu.context_menu, menu);
                return true;
            }
    
            // Called each time the action mode is shown. Always called after
            // onCreateActionMode, and might be called multiple times if the mode
            // is invalidated.
            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return false; // Return false if nothing is done.
            }
    
            // Called when the user selects a contextual menu item.
            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
               switch (item.getItemId()) {
                    case R.id.menu_share:
                        shareCurrentItem();
                        mode.finish(); // Action picked, so close the CAB.
                        return true;
                    default:
                        return false;
                }
            }
    
            // Called when the user exits the action mode.
            @Override
            public void onDestroyActionMode(ActionMode mode) {
                actionMode = null;
            }
        };
        

    Diese Ereignis-Callbacks sind fast genau dieselben wie die Callbacks für das Optionsmenü, mit der Ausnahme, dass bei jedem dieser Callbacks auch das mit dem Ereignis verknüpfte ActionMode-Objekt übergeben wird. Mit ActionMode APIs kannst du verschiedene Änderungen am CAB vornehmen, z. B. den Titel und den Untertitel mit setTitle() und setSubtitle() überarbeiten. Letzteres ist nützlich, um anzugeben, wie viele Elemente ausgewählt sind.

    Im vorherigen Beispiel wird die Variable actionMode auf null gesetzt, wenn der Aktionsmodus zerstört wird. Im nächsten Schritt erfahren Sie, wie die Variable initialisiert wird und wie das Speichern der Mitgliedsvariablen in Ihrer Aktivität oder Ihrem Fragment nützlich sein kann.

  2. Rufen Sie startActionMode() auf, wenn die Leiste angezeigt werden soll, z. B. wenn der Nutzer die Ansicht gedrückt hält.

    Kotlin

        someView.setOnLongClickListener { view ->
            // Called when the user performs a touch & hold on someView.
            when (actionMode) {
                null -> {
                    // Start the CAB using the ActionMode.Callback defined earlier.
                    actionMode = activity?.startActionMode(actionModeCallback)
                    view.isSelected = true
                    true
                }
                else -> false
            }
        }
        

    Java

        someView.setOnLongClickListener(new View.OnLongClickListener() {
            // Called when the user performs a touch & hold on someView.
            public boolean onLongClick(View view) {
                if (actionMode != null) {
                    return false;
                }
    
                // Start the CAB using the ActionMode.Callback defined earlier.
                actionMode = getActivity().startActionMode(actionModeCallback);
                view.setSelected(true);
                return true;
            }
        });
        

    Wenn Sie startActionMode() aufrufen, gibt das System die erstellte ActionMode zurück. Wenn Sie diesen Wert in einer Mitgliedsvariablen speichern, können Sie die Kontextaktionsleiste als Reaktion auf andere Ereignisse ändern. Im vorherigen Beispiel wird ActionMode verwendet, um sicherzustellen, dass die ActionMode-Instanz nicht neu erstellt wird, wenn sie bereits aktiv ist. Dazu wird geprüft, ob das Mitglied null ist, bevor der Aktionsmodus gestartet wird.

Pop-up-Menü erstellen

Ein Bild, das ein Pop-up-Menü in der Gmail App zeigt, das am Dreipunkt-Menü rechts oben verankert ist.
Abbildung 4: Ein Pop-up-Menü in der Gmail App, das an der Dreipunkt-Schaltfläche rechts oben angedockt ist.

Ein PopupMenu ist ein modales Menü, das an einem View verankert ist. Sie wird unter der Ankeransicht angezeigt, sofern genügend Platz vorhanden ist, andernfalls darüber. Sie eignet sich für Folgendes:

  • Ein Überlaufmenü für Aktionen, die sich auf bestimmte Inhalte beziehen, z. B. die E-Mail-Header in Gmail, wie in Abbildung 4 dargestellt.
  • Ein zweiter Teil eines Befehlssatzes, z. B. eine Schaltfläche mit der Bezeichnung Hinzufügen, die ein Pop-up-Menü mit verschiedenen Hinzufügen-Optionen öffnet.
  • Ein Menü ähnlich einem Spinner, das keine dauerhafte Auswahl beibehält.

Wenn Sie Ihr Menü in XML definieren, können Sie das Pop-up-Menü so anzeigen:

  1. Erstellen Sie eine Instanz von PopupMenu mit dem Konstruktor, der die aktuelle App Context und die View annimmt, an die das Menü angedockt ist.
  2. Mit MenuInflater kannst du deine Menüressource in das Menu-Objekt einfügen, das von PopupMenu.getMenu() zurückgegeben wird.
  3. PopupMenu.show() anrufen.

Hier ist beispielsweise eine Schaltfläche zu sehen, die ein Pop-up-Menü öffnet:

<ImageButton
    android:id="@+id/dropdown_menu"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:contentDescription="@string/descr_overflow_button"
    android:src="@drawable/arrow_drop_down" />

Das Pop-up-Menü kann dann so aussehen:

Kotlin

findViewById<ImageButton>(R.id.dropdown_menu).setOnClickListener {
    val popup = PopupMenu(this, it)
    val inflater: MenuInflater = popup.menuInflater
    inflater.inflate(R.menu.actions, popup.menu)
    popup.show()
}

Java

findViewById(R.id.dropdown_menu).setOnClickListener(v -> {
    PopupMenu popup = new PopupMenu(this, v);
    popup.getMenuInflater().inflate(R.menu.actions, popup.getMenu());
    popup.show();
});

Das Menü wird geschlossen, wenn der Nutzer einen Artikel auswählt oder außerhalb des Menübereichs tippt. Mit PopupMenu.OnDismissListener können Sie das Ereignis „Schließen“ erfassen.

Click-Events verarbeiten

Wenn eine Aktion ausgeführt werden soll, wenn der Nutzer einen Menüpunkt auswählt, implementiere die PopupMenu.OnMenuItemClickListener-Oberfläche und registriere sie bei deiner PopupMenu, indem du setOnMenuItemclickListener() aufrufst. Wenn der Nutzer einen Artikel auswählt, ruft das System den onMenuItemClick()-Callback in Ihrer Benutzeroberfläche auf.

Das ist im folgenden Beispiel zu sehen:

Kotlin

fun showMenu(v: View) {
    PopupMenu(this, v).apply {
        // MainActivity implements OnMenuItemClickListener.
        setOnMenuItemClickListener(this@MainActivity)
        inflate(R.menu.actions)
        show()
    }
}

override fun onMenuItemClick(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.archive -> {
            archive(item)
            true
        }
        R.id.delete -> {
            delete(item)
            true
        }
        else -> false
    }
}

Java

public void showMenu(View v) {
    PopupMenu popup = new PopupMenu(this, v);

    // This activity implements OnMenuItemClickListener.
    popup.setOnMenuItemClickListener(this);
    popup.inflate(R.menu.actions);
    popup.show();
}

@Override
public boolean onMenuItemClick(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.archive:
            archive(item);
            return true;
        case R.id.delete:
            delete(item);
            return true;
        default:
            return false;
    }
}

Menügruppe erstellen

Eine Menügruppe besteht aus einer Reihe von Menüelementen mit bestimmten gemeinsamen Merkmalen. Mit einer Gruppe haben Sie folgende Möglichkeiten:

Sie können eine Gruppe erstellen, indem Sie <item>-Elemente in einem <group>-Element in Ihrer Menüressource verschachteln oder eine Gruppen-ID mit der Methode add() angeben.

Hier ein Beispiel für eine Menüressource mit einer Gruppe:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_save"
          android:icon="@drawable/menu_save"
          android:title="@string/menu_save" />
    <!-- menu group -->
    <group android:id="@+id/group_delete">
        <item android:id="@+id/menu_archive"
              android:title="@string/menu_archive" />
        <item android:id="@+id/menu_delete"
              android:title="@string/menu_delete" />
    </group>
</menu>

Die Elemente in der Gruppe werden auf derselben Ebene wie das erste Element angezeigt. Alle drei Elemente im Menü sind Geschwisterelemente. Sie können die Merkmale der beiden Elemente in der Gruppe jedoch ändern, indem Sie auf die Gruppen-ID verweisen und die oben genannten Methoden verwenden. Außerdem werden gruppierte Elemente nie getrennt. Wenn Sie beispielsweise android:showAsAction="ifRoom" für jedes Element deklarieren, werden beide in der Aktionsleiste oder im Aktionsoverflow angezeigt.

Ankreuzbare Menüpunkte verwenden

Abbildung 5: Ein Untermenü mit ankreuzbaren Elementen.

Ein Menü kann als Benutzeroberfläche zum Aktivieren und Deaktivieren von Optionen nützlich sein. Verwenden Sie ein Kästchen für eigenständige Optionen oder Optionsfelder für Gruppen von sich gegenseitig ausschließenden Optionen. Abbildung 5 zeigt ein Untermenü mit Elementen, die über Optionsfelder aktiviert werden können.

Sie können das Ankreuzen für einzelne Menüpunkte mit dem android:checkable-Attribut im <item>-Element oder für eine ganze Gruppe mit dem android:checkableBehavior-Attribut im <group>-Element definieren. In diesem Beispiel können alle Elemente dieser Menügruppe mit einem Optionsfeld angeklickt werden:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
        <item android:id="@+id/red"
              android:title="@string/red" />
        <item android:id="@+id/blue"
              android:title="@string/blue" />
    </group>
</menu>

Für das android:checkableBehavior-Attribut sind folgende Werte zulässig:

single
Es kann jeweils nur ein Element aus der Gruppe ausgewählt werden, was zu Optionsfeldern führt.
all
Alle Elemente können ausgewählt werden, was zu Kästchen führt.
none
Keine Elemente können angeklickt werden.

Sie können einem Element mit dem Attribut android:checked im Element <item> einen standardmäßigen angeklickten Status zuweisen und ihn im Code mit der Methode setChecked() ändern.

Wenn ein anklickbares Element ausgewählt wird, ruft das System die entsprechende Rückrufmethode für das ausgewählte Element auf, z. B. onOptionsItemSelected(). Hier legen Sie den Status des Kästchens fest, da sich der Status eines Kästchens oder einer Optionsschaltfläche nicht automatisch ändert. Sie können den aktuellen Status des Artikels, wie er vor der Auswahl durch den Nutzer war, mit isChecked() abfragen und dann den angeklickten Status mit setChecked() festlegen. Das ist im folgenden Beispiel zu sehen:

Kotlin

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.vibrate, R.id.dont_vibrate -> {
            item.isChecked = !item.isChecked
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Java

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.vibrate:
        case R.id.dont_vibrate:
            if (item.isChecked()) item.setChecked(false);
            else item.setChecked(true);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Wenn Sie den angeklickten Status nicht so festlegen, ändert sich der sichtbare Status des Kästchens oder Optionsfelds nicht, wenn der Nutzer es auswählt. Wenn Sie den Status festlegen, wird durch die Aktivität der angeklickte Status des Artikels beibehalten. Wenn der Nutzer das Menü später öffnet, ist der von Ihnen festgelegte angeklickte Status sichtbar.

Menüpunkte basierend auf einem Intent hinzufügen

Manchmal soll ein Menüpunkt eine Aktivität mithilfe einer Intent starten, unabhängig davon, ob es sich um eine Aktivität in Ihrer App oder in einer anderen App handelt. Wenn Sie den Intent kennen, den Sie verwenden möchten, und einen bestimmten Menüpunkt haben, mit dem der Intent gestartet wird, können Sie den Intent mit startActivity() während der entsprechenden Rückrufmethode für die Artikelauswahl ausführen, z. B. den onOptionsItemSelected()-Rückruf.

Wenn Sie sich jedoch nicht sicher sind, ob das Gerät des Nutzers eine App enthält, die den Intent verarbeitet, kann das Hinzufügen eines Menüpunkts, der ihn aufruft, dazu führen, dass der Menüpunkt nicht funktioniert, da der Intent möglicherweise nicht auf eine Aktivität verweist. Um dieses Problem zu lösen, können Sie Ihrem Menü auf Android-Geräten dynamisch Menüpunkte hinzufügen, wenn Android Aktivitäten auf dem Gerät erkennt, die Ihre Absicht verarbeiten.

So fügen Sie Menüpunkte basierend auf verfügbaren Aktivitäten hinzu, die eine Absicht akzeptieren:

  1. Definieren Sie eine Absicht mit der Kategorie CATEGORY_ALTERNATIVE, CATEGORY_SELECTED_ALTERNATIVE oder beiden sowie allen anderen Anforderungen.
  2. Rufen Sie Menu.addIntentOptions() an. Android sucht dann nach Apps, die die Absicht ausführen können, und fügt sie dem Menü hinzu.

Wenn keine Apps installiert sind, die dem Intent entsprechen, werden keine Menüpunkte hinzugefügt.

Das ist im folgenden Beispiel zu sehen:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    super.onCreateOptionsMenu(menu)

    // Create an Intent that describes the requirements to fulfill, to be
    // included in the menu. The offering app must include a category value
    // of Intent.CATEGORY_ALTERNATIVE.
    val intent = Intent(null, dataUri).apply {
        addCategory(Intent.CATEGORY_ALTERNATIVE)
    }

    // Search and populate the menu with acceptable offering apps.
    menu.addIntentOptions(
            R.id.intent_group,  // Menu group to which new items are added.
            0,                  // Unique item ID (none).
            0,                  // Order for the items (none).
            this.componentName, // The current activity name.
            null,               // Specific items to place first (none).
            intent,             // Intent created above that describes the requirements.
            0,                  // Additional flags to control items (none).
            null)               // Array of MenuItems that correlate to specific items (none).

    return true
}

Java

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

    // Create an Intent that describes the requirements to fulfill, to be
    // included in the menu. The offering app must include a category value
    // of Intent.CATEGORY_ALTERNATIVE.
    Intent intent = new Intent(null, dataUri);
    intent.addCategory(Intent.CATEGORY_ALTERNATIVE);

    // Search and populate the menu with acceptable offering apps.
    menu.addIntentOptions(
         R.id.intent_group,         // Menu group to which new items are added.
         0,                         // Unique item ID (none).
         0,                         // Order for the items (none).
         this.getComponentName(),   // The current activity name.
         null,                      // Specific items to place first (none).
         intent,                    // Intent created above that describes the requirements.
         0,                         // Additional flags to control items (none).
         null);                     // Array of MenuItems that correlate to specific items (none).

    return true;
}

Für jede Aktivität, die einen Intent-Filter enthält, der mit dem definierten Intent übereinstimmt, wird ein Menüpunkt hinzugefügt. Dabei wird der Wert in android:label des Intent-Filters als Menüpunkttitel und das App-Symbol als Menüpunktsymbol verwendet. Die Methode addIntentOptions() gibt die Anzahl der hinzugefügten Menüpunkte zurück.

Aktivitäten zu anderen Menüs hinzufügen lassen

Sie können die Dienste Ihrer Aktivität anderen Apps anbieten, damit Ihre App in das Menü anderer Apps aufgenommen wird. Dabei werden die oben beschriebenen Rollen umgekehrt.

Wenn Sie in anderen App-Menüs enthalten sein möchten, definieren Sie einen Intent-Filter wie gewohnt, geben Sie aber die Werte CATEGORY_ALTERNATIVE oder CATEGORY_SELECTED_ALTERNATIVE oder beide für die Kategorie des Intent-Filters an. Das ist im folgenden Beispiel zu sehen:

<intent-filter label="@string/resize_image">
    ...
    <category android:name="android.intent.category.ALTERNATIVE" />
    <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
    ...
</intent-filter>

Weitere Informationen zum Erstellen von Intent-Filtern finden Sie unter Intents und Intent-Filter.