Speisekarten hinzufügen

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

Menüs sind in vielen Arten von Apps eine gängige Komponente der Benutzeroberfläche. Mit den Menu APIs kannst du Nutzern Aktionen und andere Optionen in deinen Aktivitäten präsentieren, um für eine vertraute und konsistente Umgebung zu sorgen.

Bild, das ein Beispiel für ein Dreipunkt-Menü zeigt
Abbildung 1. Ein Menü, das durch Tippen auf das Dreipunkt-Menü ausgelöst wird.

In diesem Dokument wird beschrieben, wie du die drei grundlegenden Arten von Menüs oder Aktionspräsentationen unter allen Android-Versionen erstellst:

Menü „Optionen“ und App-Leiste
Das Optionsmenü ist die primäre Sammlung von Menüpunkten für eine Aktivität. Hier platzieren Sie Aktionen, die sich global auf die Anwendung auswirken, z. B. „Suche“, „E-Mail schreiben“ und „Einstellungen“.

Weitere Informationen finden Sie im Abschnitt Optionsmenü erstellen.

Kontextmenü und Modus für Kontextaktionen
Ein Kontextmenü ist ein unverankertes Menü, das angezeigt wird, wenn der Nutzer ein Element berührt und gedrückt hält. Es werden Aktionen aufgeführt, die sich auf den ausgewählten Inhalt oder Kontextframe auswirken.

Im Modus für kontextbezogene Aktionen werden Aufgaben, die sich auf den ausgewählten Inhalt 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ü zeigt eine vertikale Liste von Elementen an, die mit der Ansicht verankert ist, in der das Menü aufgerufen wird. Sie eignet sich für einen Überlauf von Aktionen, die sich auf bestimmte Inhalte beziehen, oder um Optionen für den zweiten Teil eines Befehls bereitzustellen. Aktionen in einem Pop-up-Menü wirken sich nicht direkt auf den entsprechenden Inhalt aus – dafür sind Kontextaktionen gedacht. Das Pop-up-Menü ist vielmehr für erweiterte Aktionen in Bereichen mit Inhalten in Ihrer Aktivität gedacht.

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

Speisekarte in XML definieren

Android bietet für alle Menütypen ein Standard-XML-Format zur Definition von Menüelementen. Anstatt ein Menü im Code Ihrer Aktivität zu erstellen, definieren Sie ein Menü und alle zugehörigen Elemente in einer XML-Menüressource. Anschließend können Sie die Menüressource infließen und sie als Menu-Objekt in Ihrer Aktivität oder Ihrem Fragment laden.

Die Verwendung einer Menüressource empfiehlt sich aus den folgenden Gründen:

  • Es ist einfacher, die Menüstruktur in XML zu visualisieren.
  • Er trennt den Inhalt des Menüs vom Verhaltenscode deiner App.
  • Sie können damit alternative Menükonfigurationen für verschiedene Plattformversionen, Bildschirmgrößen und andere Konfigurationen erstellen, indem Sie das Framework für App-Ressourcen nutzen.

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

<menu>
Definiert ein Menu, das ein Container für Menüelemente ist. Ein <menu>-Element muss der Stammknoten für die Datei sein und kann ein oder mehrere <item>- und <group>-Elemente enthalten.
<item>
Erstellt ein MenuItem, das ein einzelnes Element in einem Menü darstellt. Dieses Element kann ein verschachteltes <menu>-Element enthalten, um ein Untermenü zu erstellen.
<group>
Ein optionaler, unsichtbarer Container für <item>-Elemente. Sie können Menüelemente so kategorisieren, dass sie gemeinsame Attribute haben, z. B. „Aktiv“ und „Sichtbarkeit“. Weitere Informationen finden Sie im Abschnitt Speisekartengruppe erstellen.

Hier ein Beispielmenü mit dem Namen 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 <item>-Element unterstützt mehrere Attribute, mit denen Sie die Darstellung und das Verhalten eines Elements definieren können. Die Elemente im vorherigen Menü enthalten die folgenden Attribute:

android:id
Eine eindeutige Ressourcen-ID für das Element, anhand der die App das Element erkennen kann, wenn der Nutzer es auswählt.
android:icon
Ein Verweis auf ein Drawable, das als Symbol für das Element verwendet werden kann.
android:title
Ein Verweis auf einen String, der als Titel des Elements verwendet werden soll.
android:showAsAction
Die Angabe, wann und wie dieses Element als Aufgabe 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 zu Menüressourcen.

Sie können jedem Element in jedem Menü ein Untermenü hinzufügen. Dazu fügen Sie ein <menu>-Element als untergeordnetes Element von <item> hinzu. 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-App, z. B. Datei, Bearbeiten und Ansicht. Hier ein Beispiel:

<?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>

Um das Menü in Ihrer Aktivität zu verwenden, _inflate_ Sie die Menüressource und konvertieren Sie die XML-Ressource mithilfe von MenuInflater.inflate() in ein programmierbares Objekt. In den folgenden Abschnitten wird gezeigt, wie Sie ein Menü für jeden Menütyp aufblähen können.

Optionsmenü erstellen

Im Optionsmenü (siehe Abbildung 1) können Sie Aktionen und andere Optionen hinzufügen, die für den aktuellen Aktivitätskontext relevant sind, z. B. „Suche“, „E-Mail schreiben“ und „Einstellungen“.

Ein Bild, das die App-Leiste für die Google Tabellen App zeigt
Abbildung 2. Die Google Tabellen-App mit mehreren Schaltflächen, darunter die Aktionsüberlaufschaltfläche.

Sie können Elemente für das Optionsmenü aus Ihrer untergeordneten Activity-Klasse oder einer Fragment-Unterklasse deklarieren. Wenn sowohl in Ihrer Aktivität als auch in Ihren Fragmenten Elemente für das Optionsmenü deklariert sind, werden die Elemente in der UI kombiniert. Die Elemente der Aktivität werden zuerst angezeigt, gefolgt von denen der einzelnen Fragmente, und zwar in der Reihenfolge, in der die Fragmente zur Aktivität hinzugefügt werden. Bei Bedarf kannst du die Menüpunkte mit dem Attribut android:orderInCategory in jeder <item>, die du verschieben möchtest, neu anordnen.

Wenn Sie das Optionsmenü für eine Aktivität angeben möchten, überschreiben Sie onCreateOptionsMenu(). Fragmente bieten einen eigenen onCreateOptionsMenu() Callback. Bei dieser Methode können Sie Ihre in XML definierte Menüressource in den Menu im Callback umwandeln. Dies wird im folgenden Beispiel veranschaulicht:

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üelemente auch mit add() hinzufügen und mit findItem() abrufen, um ihre Eigenschaften mit MenuItem APIs zu überarbeiten.

Klickereignisse verarbeiten

Wenn der Nutzer ein Element aus dem Optionsmenü auswählt, einschließlich Aufgaben in der App-Leiste, ruft das System die Methode onOptionsItemSelected() Ihrer Aktivität auf. Bei dieser Methode wird die ausgewählte MenuItem übergeben. Du kannst den Artikel identifizieren, indem du getItemId() aufrufst. Dadurch wird die eindeutige ID für den Menüpunkt zurückgegeben, die durch das Attribut android:id in der Menüressource oder mit einer Ganzzahl definiert wird, die der Methode add() übergeben wird. Du kannst 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 ein Menüpunkt erfolgreich verarbeitet wurde, geben Sie true zurück. Wenn Sie das Menüelement nicht verarbeiten, rufen Sie die Implementierung der Basisklasse 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 auf und dann für jedes Fragment in der Reihenfolge, in der die Fragmente hinzugefügt werden, bis eines true zurückgibt oder alle Fragmente aufgerufen werden.

Menüelemente zur Laufzeit ändern

Nachdem das System onCreateOptionsMenu() aufgerufen hat, wird eine Instanz des von Ihnen ausgefüllten Menu beibehalten und onCreateOptionsMenu() wird nur dann noch einmal aufgerufen, wenn das Menü ungültig wird. Verwenden Sie onCreateOptionsMenu() jedoch nur, um den Anfangsmenüstatus zu erstellen und nicht, um Änderungen während des Aktivitätslebenszyklus vorzunehmen.

Wenn Sie das Optionsmenü basierend auf Ereignissen ändern möchten, die während des Aktivitätslebenszyklus auftreten, können Sie dies in der Methode onPrepareOptionsMenu() tun. Bei dieser Methode wird das derzeit vorhandene Menu-Objekt an Sie übergeben, sodass Sie es ändern können, z. B. durch Hinzufügen, Entfernen oder Deaktivieren von Elementen. Sie 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 Sie eine Menüaktualisierung vornehmen möchten, rufen Sie invalidateOptionsMenu() auf, um das System dazu aufzufordern, onPrepareOptionsMenu() aufzurufen.

Kontextmenü erstellen

Bild, das ein unverankertes Kontextmenü zeigt
Abbildung 3: Ein unverankertes Kontextmenü.

Ein Kontextmenü bietet Aktionen, die ein bestimmtes Element oder einen Kontextframe in der UI betreffen. Sie können für jede Ansicht ein Kontextmenü bereitstellen. Diese werden jedoch am häufigsten für Elemente in RecylerView oder anderen Ansichtssammlungen verwendet, in denen der Nutzer direkte Aktionen für jedes Element ausführen kann.

Es gibt zwei Möglichkeiten, Kontextaktionen bereitzustellen:

  • In einem unverankerten Kontextmenü: Ein Menü wird, ähnlich wie ein Dialogfeld, als unverankerte Liste von Menüelementen angezeigt, wenn der Nutzer eine Ansicht berührt und hält, in der die Unterstützung für ein Kontextmenü deklariert wird. Nutzer können eine kontextbezogene Aktion für jeweils ein Element ausführen.
  • Im Modus für kontextbezogene Aktionen Dieser Modus ist eine Systemimplementierung von ActionMode, bei der oben auf dem Bildschirm eine kontextbezogene Aktionsleiste(CAB) mit Aktionselementen angezeigt wird, die sich auf die ausgewählten Elemente auswirken. Wenn dieser Modus aktiviert ist, können Nutzer eine Aktion für mehrere Elemente gleichzeitig ausführen, sofern deine App dies unterstützt.

Unverankertes Kontextmenü erstellen

So stellen Sie ein unverankertes Kontextmenü bereit:

  1. Registrieren Sie die View, mit der das Kontextmenü verknüpft ist, indem Sie registerForContextMenu() aufrufen und das View übergeben.

    Wenn Ihre Aktivität eine RecyclerView verwendet und Sie möchten, dass jedes Element dasselbe Kontextmenü bereitstellt, registrieren Sie alle Elemente für ein Kontextmenü, indem Sie RecyclerView an registerForContextMenu() übergeben.

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

    Wenn die registrierte Ansicht ein „Berühren und halten“-Ereignis empfängt, wird vom System die Methode onCreateContextMenu() aufgerufen. Hier definieren Sie die Menüpunkte, in der Regel durch Aufblähen einer Menüressource, wie im folgenden Beispiel gezeigt:

    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 können Sie das Kontextmenü über eine Menüressource erweitern. Die Parameter der Callback-Methode umfassen das vom Nutzer ausgewählte View und ein ContextMenu.ContextMenuInfo-Objekt, das zusätzliche Informationen zum ausgewählten Element liefert. Wenn Ihre Aktivität mehrere Ansichten hat, die jeweils ein anderes Kontextmenü bieten, können Sie diese Parameter verwenden, um zu bestimmen, welches Kontextmenü erweitert werden soll.

  3. Implementieren Sie onContextItemSelected(), wie im folgenden Beispiel gezeigt. Wenn der Nutzer einen Menüpunkt auswählt, wird diese Methode vom System aufgerufen, damit du die entsprechende Aktion ausführen kannst.

    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 des ausgewählten Menüpunkts ab, die Sie jedem Menüpunkt in XML mithilfe des Attributs android:id zuweisen, wie unter Definieren eines Menüs in XML beschrieben.

    Wenn ein Menüpunkt erfolgreich verarbeitet wurde, geben Sie true zurück. Wenn Sie das Menüelement nicht verarbeiten, übergeben Sie es an die Implementierung der übergeordneten Klasse. Wenn Ihre Aktivität Fragmente enthält, empfängt die Aktivität diesen Callback zuerst. Wenn die Basisklasse aufgerufen wird, wenn sie nicht verarbeitet wird, übergibt das System das Ereignis in jedem Fragment nacheinander an die entsprechende Callback-Methode, und zwar in der Reihenfolge, in der die einzelnen Fragmente hinzugefügt werden, bis true oder false zurückgegeben wird. Die Standardimplementierungen für Activity und android.app.Fragment geben false zurück. Daher wird die Basisklasse immer aufgerufen, wenn sie nicht verarbeitet wird.

Modus für kontextbezogene Aktionen verwenden

Der Modus für kontextbezogene Aktionen ist eine Systemimplementierung von ActionMode, die die Nutzerinteraktion auf die Ausführung von kontextbezogenen Aktionen konzentriert. Wenn ein Nutzer diesen Modus durch Auswahl eines Elements aktiviert, wird oben auf dem Bildschirm eine kontextbezogene Aktionsleiste angezeigt. Dort werden die Aktionen angezeigt, die der Nutzer für 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. Außerdem kann der Nutzer die Auswahl von Elementen aufheben und innerhalb der Aktivität weiter navigieren. Der Aktionsmodus ist deaktiviert und die kontextbezogene Aktionsleiste wird ausgeblendet, wenn der Nutzer die Auswahl aller Elemente aufhebt, auf die Schaltfläche „Zurück“ oder links auf der Leiste auf die Aktion Fertig tippt.

Bei Ansichten mit kontextbezogenen Aktionen rufen Sie normalerweise den Modus für kontextbezogene Aktionen auf, wenn eines oder beide der folgenden Ereignisse eintreten:

  • Der Nutzer berührt und halte die Ansicht.
  • Der Nutzer wählt ein Kästchen oder eine ähnliche UI-Komponente in der Ansicht aus.

Wie Ihre Anwendung 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 für einzelne, beliebige Ansichten.
  • Bei kontextbezogenen Batchaktionen für Elementgruppen in einer RecyclerView können Nutzer mehrere Elemente auswählen und eine Aktion für alle ausführen.

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

Modus für kontextbezogene Aktionen für einzelne Ansichten aktivieren

Wenn der Modus für kontextbezogene Aktionen nur aufgerufen werden soll, wenn der Nutzer bestimmte Ansichten auswählt, gehen Sie so vor:

  1. Implementieren Sie die ActionMode.Callback-Schnittstelle wie im folgenden Beispiel gezeigt. In den zugehörigen Callback-Methoden können Sie die Aktionen für die kontextbezogene Aktionsleiste angeben, auf Klickereignisse für 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 mit den Callbacks für das Optionsmenü identisch. Der einzige Unterschied besteht darin, dass bei jedem dieser Callbacks auch das mit dem Ereignis verknüpfte ActionMode-Objekt übergeben wird. Mit ActionMode APIs können Sie verschiedene Änderungen am CAB vornehmen, z. B. den Titel und den Untertitel mit setTitle() und setSubtitle() überarbeiten. Damit lässt sich angeben, wie viele Elemente ausgewählt sind.

    Im vorherigen Beispiel wird die Variable actionMode auf null gesetzt, wenn der Aktionsmodus gelöscht wird. Prüfen Sie im nächsten Schritt, wie sie initialisiert wird und wie es nützlich sein kann, die Member-Variable in Ihrer Aktivität oder Ihrem Fragment zu speichern.

  2. Rufen Sie startActionMode() auf, wenn die Leiste eingeblendet 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 den erstellten ActionMode zurück. Wenn Sie dies in einer Mitgliedsvariable speichern, können Sie als Reaktion auf andere Ereignisse Änderungen an der kontextbezogenen Aktionsleiste vornehmen. Im vorherigen Beispiel wird mit ActionMode dafür gesorgt, dass die Instanz ActionMode nicht neu erstellt wird, wenn sie bereits aktiv ist. Dazu wird vor dem Starten des Aktionsmodus geprüft, ob das Mitglied null ist.

Pop-up-Menü erstellen

Ein Bild mit einem Pop-up-Menü in der Gmail App, das mit der Dreipunkt-Menü-Schaltfläche oben rechts verankert ist.
Abbildung 4: Ein Pop-up-Menü in der Gmail App, das auf der Dreipunkt-Menüschaltfläche rechts oben verankert ist.

Ein PopupMenu ist ein modales Menü, das mit einer View verknüpft ist. Sie wird unter der Ankeransicht eingeblendet, wenn genug Platz ist, oder über der Ansicht. Sie ist in folgenden Fällen nützlich:

  • Bereitstellung eines Dreipunkt-Menüs für Aktionen, die sich auf bestimmte Inhalte beziehen, z. B. die E-Mail-Header von Gmail (siehe Abbildung 4).
  • Hinzufügen eines zweiten Teils eines Befehlssatzes, z. B. über die Schaltfläche Add (Hinzufügen), über die ein Pop-up-Menü mit verschiedenen Add-Optionen geöffnet wird.
  • Ein Menü bereitstellen, das einem Spinner ähnelt, das keine dauerhafte Auswahl beibehält.

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

  1. Instanziieren Sie ein PopupMenu mit seinem Konstruktor, der die aktuelle Context der Anwendung und die View verwendet, mit der das Menü verankert ist.
  2. Mit MenuInflater können Sie Ihre Menüressource in das von PopupMenu.getMenu() zurückgegebene Menu-Objekt erweitern.
  3. PopupMenu.show() anrufen.

Hier sehen Sie beispielsweise eine Schaltfläche, die ein Pop-up-Menü anzeigt:

<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" />

Die Aktivität kann dann das Pop-up-Menü wie folgt anzeigen:

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 ein Element auswählt oder außerhalb des Menübereichs tippt. Sie können mit PopupMenu.OnDismissListener auf das take-Ereignis warten.

Klickereignisse verarbeiten

Damit eine Aktion ausgeführt werden kann, wenn der Nutzer einen Menüpunkt auswählt, implementieren Sie die PopupMenu.OnMenuItemClickListener-Schnittstelle und registrieren sie mit Ihrer PopupMenu. Rufen Sie dazu setOnMenuItemclickListener() auf. Wenn der Nutzer ein Element auswählt, ruft das System den onMenuItemClick()-Callback auf Ihrer Benutzeroberfläche auf.

Dies wird im folgenden Beispiel veranschaulicht:

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;
    }
}

Speisekartengruppe erstellen

Eine Menügruppe ist eine Sammlung von Menüpunkten, die bestimmte Eigenschaften gemeinsam haben. 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, die eine Gruppe enthält:

<?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 gleichgeordnet. Sie können jedoch die Merkmale der beiden Elemente in der Gruppe ändern, indem Sie auf die Gruppen-ID verweisen und die vorherigen Methoden verwenden. Außerdem trennt das System niemals gruppierte Elemente. Wenn Sie beispielsweise android:showAsAction="ifRoom" für jedes Element deklarieren, werden beide in der Aktionsleiste oder beide im Aktionsüberlauf angezeigt.

Aktivierbare Menüpunkte verwenden

Abbildung 5. Ein Untermenü mit auswählbaren Elementen.

Ein Menü kann als Oberfläche zum Aktivieren und Deaktivieren von Optionen nützlich sein. Verwenden Sie beispielsweise 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 mit Optionsfeldern markiert werden können.

Sie können das überprüfbare Verhalten für einzelne Menüpunkte mit dem Attribut android:checkable im Element <item> oder für eine ganze Gruppe mit dem Attribut android:checkableBehavior im Element <group> definieren. Beispielsweise können alle Elemente in dieser Menügruppe über ein Optionsfeld ausgewählt 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 Attribut android:checkableBehavior ist eine der folgenden Optionen zulässig:

single
Nur ein Element aus der Gruppe kann überprüft werden, sodass Optionsfelder angezeigt werden.
all
Alle Elemente können aktiviert werden, sodass Kästchen angezeigt werden.
none
Es können keine Elemente ausgewählt werden.

Sie können einen standardmäßig aktivierten Status auf ein Element anwenden, indem Sie das Attribut android:checked im Element <item> verwenden und ihn im Code mit der Methode setChecked() ändern.

Wenn ein anklickbares Element ausgewählt ist, ruft das System die entsprechende Callback-Methode für das Element auf, z. B. onOptionsItemSelected(). Hier legen Sie den Status des Kästchens fest, da sich der Status eines Kästchens oder Optionsfelds nicht automatisch ändert. Sie können den aktuellen Status des Elements – so, wie er vor der Auswahl des Nutzers war – mit isChecked() abfragen und dann den überprüften Status mit setChecked() festlegen. Dies wird im folgenden Beispiel gezeigt:

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 Status „Aktiviert“ nicht auf diese Weise festlegen, ändert sich der sichtbare Status des Kästchens oder Optionsfelds nicht, wenn der Nutzer es auswählt. Wenn Sie den Status festlegen, wird der aktivierte Status des Elements für die Aktivität beibehalten. Wenn der Nutzer das Menü später öffnet, ist also der von Ihnen festgelegte Status „Aktiviert“ sichtbar.

Menüpunkte basierend auf einem Intent hinzufügen

Manchmal soll ein Menüpunkt eine Aktivität mit einem Intent starten, unabhängig davon, ob es sich um eine Aktivität in Ihrer oder einer anderen App handelt. Wenn Sie den zu verwendenden Intent kennen und einen bestimmten Menüpunkt haben, der den Intent initiiert, können Sie den Intent mit startActivity() während der entsprechenden Callback-Methode (z. B. onOptionsItemSelected()) ausführen.

Wenn Sie 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 den Intent aufruft, dazu führen, dass der Intent nicht mehr funktioniert, da der Intent möglicherweise nicht zu einer Aktivität aufgelöst wird. Um dieses Problem zu lösen, kannst du in Android Menüelemente dynamisch zu deinem Menü hinzufügen, wenn Android auf dem Gerät Aktivitäten findet, die deine Absicht behandeln.

So fügen Sie Menüpunkte anhand der verfügbaren Aktivitäten hinzu, die einen Intent akzeptieren:

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

Wenn keine Apps installiert sind, die den Intent erfüllen, werden keine Menüelemente hinzugefügt.

Dies wird im folgenden Beispiel veranschaulicht:

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 gefundene Aktivität, die einen mit dem definierten Intent übereinstimmenden Intent-Filter bereitstellt, wird eine Menüoption hinzugefügt. Dabei wird der Wert im android:label des Intent-Filters als Titel des Menüpunkts und das App-Symbol als Menüelementsymbol verwendet. Die Methode addIntentOptions() gibt die Anzahl der hinzugefügten Menüpunkte zurück.

Aktivitäten anderen Menüs hinzufügen lassen

Sie können die Dienste Ihrer Aktivitäten anderen Anwendungen anbieten, damit Ihre Anwendung in das Menü anderer aufgenommen werden kann. Dadurch werden die zuvor beschriebenen Rollen umgekehrt.

Wenn Sie es in andere App-Menüs aufnehmen möchten, definieren Sie wie gewohnt einen Intent-Filter und geben Sie dabei für die Intent-Filterkategorie entweder den Wert CATEGORY_ALTERNATIVE oder CATEGORY_SELECTED_ALTERNATIVE oder beides an. Dies wird im folgenden Beispiel veranschaulicht:

<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 Schreiben von Intent-Filtern finden Sie unter Intents und Intent-Filter.