Menüs sind eine gängige Benutzeroberflächenkomponente in vielen Arten von Apps. Um eine vertraute und einheitliche Nutzererfahrung zu bieten, verwenden Sie die Menu APIs, um Nutzeraktionen und andere Optionen in Ihren Aktivitäten zu präsentieren.
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ü ist die primäre Sammlung von Menüelementen für eine Aktivität. Hier platzieren Sie Aktionen, die sich global auf die App auswirken, z. B. „Suchen“, „E‑Mail verfassen“ 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 berührt und hält. Sie bietet Aktionen, die sich auf den ausgewählten Inhalt oder Kontextrahmen auswirken.
Im kontextbezogenen Aktionsmodus werden Aktionsschaltflächen, die sich auf die ausgewählten Inhalte beziehen, 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ü
- In einem Pop-up-Menü wird eine vertikale Liste von Elementen angezeigt, die an die Ansicht angehängt ist, über die das Menü aufgerufen wird. Sie eignet sich gut, um eine Vielzahl von Aktionen im Zusammenhang mit bestimmten Inhalten oder Optionen für den zweiten Teil eines Befehls bereitzustellen. Aktionen in einem Pop-up-Menü wirken sich nicht direkt auf die entsprechenden Inhalte aus. Dafür sind Kontextaktionen vorgesehen. Das Pop-up-Menü ist für erweiterte Aktionen vorgesehen, 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üelementen. Anstatt ein Menü im Code Ihrer Aktivität zu erstellen, definieren Sie ein Menü und alle zugehörigen Elemente in einer Menüressource in XML. Anschließend können Sie die Menüressource 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.
- Dadurch wird der Inhalt für das Menü vom Verhaltenscode Ihrer App getrennt.
- Damit können Sie alternative Menükonfigurationen für verschiedene Plattformversionen, Bildschirmgrößen und andere Konfigurationen erstellen, indem Sie das Framework für App-Ressourcen nutzen.
Um ein Menü zu definieren, erstellen Sie eine XML-Datei im Verzeichnis res/menu/ Ihres Projekts und erstellen Sie das Menü mit den folgenden Elementen:
<menu>- Definiert ein
Menu, das ein Container für Menüpunkte 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. Damit können Sie Menüelemente kategorisieren, sodass 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 <item>-Element unterstützt mehrere Attribute, mit denen Sie das Erscheinungsbild und Verhalten eines Elements definieren können. Die Elemente im vorherigen Menü haben die folgenden Attribute:
android:id- Eine Ressourcen-ID, die für das Element eindeutig ist und mit der die App das Element erkennen kann, wenn der Nutzer es auswählt.
android:icon- Eine Referenz auf ein „Drawable“, das als Symbol für das Element verwendet werden soll.
android:title- Ein Verweis auf eine Zeichenfolge, die als Titel des Elements verwendet werden soll.
android:showAsAction- Die Spezifikation dafür, wann und wie dieses Element als Aktionsschaltfläche in der App-Leiste angezeigt wird.
Das sind die wichtigsten Attribute, die Sie verwenden. Es gibt aber 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 in Themen unterteilt werden können, z. B. Elemente in der Menüleiste einer PC-App wie Datei, Bearbeiten und Ansicht. Siehe folgendes 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>
Wenn Sie das Menü in Ihrer Aktivität verwenden möchten, müssen Sie die Menüressource _aufblasen_ und die XML-Ressource mit MenuInflater.inflate() in ein programmierbares Objekt umwandeln.
In den folgenden Abschnitten wird gezeigt, wie Sie ein Menü für jeden Menütyp aufblasen.
Optionsmenü erstellen
Im Optionsmenü, wie in Abbildung 1 dargestellt, können Sie Aktionen und andere Optionen einfügen, die für den aktuellen Aktivitätskontext relevant sind, z. B. „Suchen“, „E‑Mail verfassen“ und „Einstellungen“.
Sie können Elemente für das Optionsmenü in Ihrer Activity-Unterklasse oder einer Fragment-Unterklasse deklarieren. Wenn sowohl in Ihrer Aktivität als auch in Ihren Fragmenten Elemente für das Optionsmenü deklariert werden, werden die Elemente in der Benutzeroberfläche kombiniert. Die Elemente der Aktivität werden zuerst angezeigt, gefolgt von denen der einzelnen Fragmente in der Reihenfolge, in der die Fragmente der Aktivität hinzugefügt werden. Bei Bedarf können Sie die Menüpunkte mit dem Attribut android:orderInCategory in jedem <item>, das Sie verschieben möchten, neu anordnen.
Wenn Sie das Optionsmenü für eine Aktivität angeben möchten, überschreiben Sie onCreateOptionsMenu().
Fragmente haben einen eigenen onCreateOptionsMenu()-Callback. Bei dieser Methode können Sie Ihre in XML definierte Menüressource in das im Callback bereitgestellte Menu einfügen. 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üpunkte auch mit add() hinzufügen und mit findItem() abrufen, um ihre Eigenschaften mit MenuItem APIs zu ändern.
Click-Events verarbeiten
Wenn der Nutzer ein Element aus dem Optionsmenü auswählt, einschließlich der Aktionsschaltflächen in der App-Leiste, ruft das System die Methode onOptionsItemSelected() der Aktivität auf. Diese Methode übergibt die ausgewählte MenuItem. Sie können das Element identifizieren, indem Sie getItemId() aufrufen. Dadurch wird die eindeutige ID für das Menüelement zurückgegeben, die durch das Attribut android:id in der Menüressource oder durch eine Ganzzahl, die an die Methode add() übergeben wird, definiert wird. Sie können diese ID mit bekannten Menüelementen 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 Sie ein Menüelement erfolgreich verarbeitet haben, geben Sie true zurück. Wenn Sie das Menüelement nicht verarbeiten, rufen Sie die Superclass-Implementierung 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 werden, bis ein Fragment true zurückgibt oder alle Fragmente aufgerufen wurden.
Menüpunkte zur Laufzeit ändern
Nachdem das System onCreateOptionsMenu() aufgerufen hat, wird eine Instanz von Menu beibehalten, die Sie ausgefüllt haben. onCreateOptionsMenu() wird erst wieder aufgerufen, wenn das Menü ungültig gemacht wird.
Verwenden Sie onCreateOptionsMenu() jedoch nur, um den ursprünglichen Menüzustand zu erstellen, und nicht, um während des Aktivitätslebenszyklus Änderungen 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 Menu-Objekt in seinem aktuellen Zustand übergeben, sodass Sie es ändern können, z. B. durch Hinzufügen, Entfernen oder Deaktivieren von Elementen.
Für Fragmente ist auch ein onPrepareOptionsMenu()-Callback verfügbar.
Das Optionsmenü gilt immer als geöffnet, wenn Menüelemente in der App-Leiste angezeigt werden. Wenn ein Ereignis eintritt und Sie eine Menüaktualisierung durchführen möchten, rufen Sie invalidateOptionsMenu() auf, um anzufordern, dass das System onPrepareOptionsMenu() aufruft.
Kontextmenü erstellen
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. Es wird jedoch am häufigsten für Elemente in einer 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 schwebenden Kontextmenü. Ein Menü wird als schwebende Liste von Menüelementen angezeigt, ähnlich wie ein Dialogfeld, wenn der Nutzer eine Ansicht berührt und hält, die ein Kontextmenü unterstützt. Nutzer können jeweils nur eine kontextbezogene Aktion für ein Element ausführen.
- Im Kontext-Aktionsbanner Dieser Modus ist eine Systemimplementierung von
ActionMode, bei der oben auf dem Bildschirm eine kontextbezogene Aktionsleiste(Contextual Action Bar, CAB) mit Aktionsschaltflächen angezeigt wird, die sich auf die ausgewählten Elemente auswirken. Wenn dieser Modus aktiv ist, können Nutzer Aktionen für mehrere Elemente gleichzeitig ausführen, sofern Ihre App dies unterstützt.
Hinweis:Kontextmenüs unterstützen keine Elementsymbolleisten und Elementsymbole.
Schwebendes Kontextmenü erstellen
So stellen Sie ein schwebendes Kontextmenü bereit:
- Registrieren Sie die
View, mit der das Kontextmenü verknüpft ist, indem SieregisterForContextMenu()aufrufen und dieViewübergeben.Wenn in Ihrer Aktivität ein
RecyclerViewverwendet wird und Sie für jedes Element dasselbe Kontextmenü verwenden möchten, registrieren Sie alle Elemente für ein Kontextmenü, indem Sie dasRecyclerViewanregisterForContextMenu()übergeben. - Implementieren Sie die Methode
onCreateContextMenu()in IhremActivityoderFragment.Wenn die registrierte Ansicht ein Touch-and-Hold-Ereignis empfängt, ruft das System Ihre
onCreateContextMenu()-Methode 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
MenuInflaterkönnen Sie das Kontextmenü aus einer Menüressource aufblähen. Die Parameter der Callback-Methode enthalten dieView, die der Nutzer auswählt, und einContextMenu.ContextMenuInfo-Objekt, das zusätzliche Informationen zum ausgewählten Element enthält. Wenn Ihre Aktivität mehrere Ansichten hat, die jeweils ein anderes Kontextmenü bieten, können Sie mit diesen Parametern festlegen, welches Kontextmenü aufgeblasen werden soll. Implementieren Sie
onContextItemSelected(), wie im folgenden Beispiel gezeigt. Wenn der Nutzer ein Menüelement 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); } }
Mit der Methode
getItemId()wird die ID für den ausgewählten Menüpunkt abgefragt, die Sie jedem Menüpunkt in XML mit dem Attributandroid:idzuweisen, wie unter Menü in XML definieren beschrieben.Wenn Sie ein Menüelement erfolgreich verarbeitet haben, geben Sie
truezurück. Wenn Sie den Menüpunkt nicht verarbeiten, übergeben Sie ihn an die Implementierung der Basisklasse. Wenn Ihre Aktivität Fragmente enthält, wird dieser Callback zuerst für die Aktivität aufgerufen. Wenn Sie die Superklasse aufrufen, wenn das Ereignis nicht verarbeitet wird, übergibt das System das Ereignis an die entsprechende Callback-Methode in jedem Fragment, jeweils einzeln, in der Reihenfolge, in der die Fragmente hinzugefügt werden, bistrueoderfalsezurückgegeben wird. Die Standardimplementierungen fürActivityundandroid.app.Fragmentgebenfalsezurück. Rufen Sie also immer die Superklasse auf, wenn die Ereignisse nicht verarbeitet werden.
Kontext-Aktionsbanner verwenden
Der Kontextaktionsmodus ist eine Systemimplementierung von ActionMode, bei der die Nutzerinteraktion auf die Ausführung von Kontextaktionen ausgerichtet ist. Wenn ein Nutzer diesen Modus durch Auswahl eines Elements aktiviert, wird oben auf dem Bildschirm eine kontextbezogene Aktionsleiste angezeigt, in der Aktionen präsentiert werden, 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 er die Auswahl von Elementen aufheben und weiterhin in der Aktivität navigieren. Der Aktionsmodus wird deaktiviert und die kontextbezogene Aktionsleiste verschwindet, wenn der Nutzer die Auswahl aller Elemente aufhebt, auf die Schaltfläche „Zurück“ oder auf die Aktion Fertig auf der linken Seite der Leiste tippt.
Bei Ansichten, die Kontextaktionen bieten, wird der Kontextaktionsmodus in der Regel aufgerufen, wenn eines oder beide der folgenden Ereignisse eintreten:
- Der Nutzer führt eine Touch-and-Hold-Geste auf der Ansicht aus.
- Der Nutzer wählt in der Ansicht ein Kästchen oder eine ähnliche UI-Komponente aus.
Wie Ihre App den Kontextaktionsmodus aufruft und das Verhalten für jede Aktion definiert, hängt von Ihrem Design ab. Es gibt zwei Designs:
- Für Kontextaktionen für einzelne, beliebige Ansichten.
- Für kontextbezogene Batchaktionen für Gruppen von Elementen in einem
RecyclerView, bei denen der Nutzer mehrere Elemente auswählen und eine Aktion für alle Elemente ausführen kann.
In den folgenden Abschnitten wird die für das erste Szenario erforderliche Einrichtung beschrieben.
Kontext-Aktionsbanner für einzelne Ansichten aktivieren
Wenn Sie den Kontext-Aktionsbanner nur aufrufen möchten, wenn der Nutzer bestimmte Ansichten auswählt, gehen Sie so vor:
- Implementieren Sie die
ActionMode.Callback-Schnittstelle wie im folgenden Beispiel gezeigt. In den 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 Event-Callbacks sind fast identisch mit den Callbacks für das Optionsmenü. Der einzige Unterschied besteht darin, dass bei jedem dieser Callbacks auch das mit dem Ereignis verknüpfte
ActionMode-Objekt übergeben wird. Mit denActionMode-APIs können Sie verschiedene Änderungen am CAB vornehmen, z. B. den Titel und Untertitel mitsetTitle()undsetSubtitle()überarbeiten. Das ist nützlich, um anzugeben, wie viele Elemente ausgewählt sind.Im vorherigen Beispiel wird die Variable
actionModeaufnullgesetzt, wenn der Aktionsmodus beendet wird. Im nächsten Schritt erfahren Sie, wie sie initialisiert wird und wie das Speichern der Mitgliedsvariable in Ihrer Aktivität oder Ihrem Fragment nützlich sein kann. - Rufen Sie
startActionMode()auf, wenn Sie die Leiste anzeigen möchten, z. B. wenn der Nutzer die Ansicht berührt und 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 erstellteActionModezurück. Wenn Sie dies in einer Membervariablen speichern, können Sie die kontextbezogene Aktionsleiste als Reaktion auf andere Ereignisse ändern. Im vorherigen Beispiel wirdActionModeverwendet, um sicherzustellen, dass dieActionMode-Instanz nicht neu erstellt wird, wenn sie bereits aktiv ist. Dazu wird geprüft, ob das Mitglied vor dem Starten des Aktionsmodus null ist.
Pop-up-Menü erstellen
Ein PopupMenu ist ein modales Menü, das an ein View angehängt ist. Sie wird unter der Ankeransicht angezeigt, wenn genügend Platz vorhanden ist, andernfalls darüber. Das ist nützlich für:
- Ein Menü im Stil eines Überlaufmenüs für Aktionen, die mit bestimmten Inhalten zusammenhängen, z. B. die E‑Mail-Kopfzeilen von Gmail (siehe Abbildung 4).
- Sie geben einen zweiten Teil eines Befehlssatzes an, z. B. eine Schaltfläche mit der Aufschrift Hinzufügen, die ein Pop-up-Menü mit verschiedenen Hinzufügen-Optionen öffnet.
- Ein Menü ähnlich einem
Spinnerwird angezeigt, in dem keine Auswahl dauerhaft gespeichert wird.
Wenn Sie Ihr Menü in XML definieren, können Sie das Pop-up-Menü so anzeigen:
- Instanziieren Sie ein
PopupMenumit seinem Konstruktor, der die aktuelle AppContextund dasView, an dem das Menü verankert ist, verwendet. - Verwenden Sie
MenuInflater, um die Menüressource in dasMenu-Objekt zu übertragen, das vonPopupMenu.getMenu()zurückgegeben wird. - Rufen Sie
PopupMenu.show()an.
Hier ist ein Beispiel für einen Button, der 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ü so 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. Mit PopupMenu.OnDismissListener können Sie auf das Ereignis „dismiss“ warten.
Click-Events verarbeiten
Wenn eine Aktion ausgeführt werden soll, wenn der Nutzer ein Menüelement auswählt, implementieren Sie die PopupMenu.OnMenuItemClickListener-Schnittstelle und registrieren Sie sie mit Ihrem PopupMenu, indem Sie setOnMenuItemclickListener() aufrufen.
Wenn der Nutzer ein Element auswählt, ruft das System den onMenuItemClick()-Callback in 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; } }
Menügruppe erstellen
Eine Menügruppe ist eine Sammlung von Menüpunkten, die bestimmte Merkmale gemeinsam haben. Mit einer Gruppe haben Sie folgende Möglichkeiten:
- Alle Elemente mit
setGroupVisible()ein- oder ausblenden. - Alle Elemente mit
setGroupEnabled()aktivieren oder deaktivieren. - Geben Sie an, ob alle Elemente mit
setGroupCheckable()geprüft werden können.
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 gleichrangig. Sie können die Attribute der beiden Elemente in der Gruppe jedoch ändern, indem Sie auf die Gruppen-ID verweisen und die oben genannten Methoden verwenden. Das System trennt gruppierte Elemente auch nie. Wenn Sie beispielsweise android:showAsAction="ifRoom" für jedes Element deklarieren, werden beide in der Aktionsleiste oder im Aktionsüberlauf angezeigt.
Ankreuzbare Menüpunkte verwenden
Ein Menü kann als Schnittstelle 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 mit Optionsfeldern ausgewählt werden können.
Sie können das Verhalten von einzelnen Menüpunkten mit dem Attribut android:checkable im Element <item> oder für eine ganze Gruppe mit dem Attribut android:checkableBehavior im Element <group> definieren. Alle Elemente in dieser Menügruppe können beispielsweise mit einem 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>
Das Attribut android:checkableBehavior akzeptiert einen der folgenden Werte:
single- Es kann nur ein Element aus der Gruppe ausgewählt werden. Das Ergebnis sind Optionsfelder.
all- Alle Elemente können ausgewählt werden, wodurch Kontrollkästchen entstehen.
none- Es sind keine Elemente prüfbar.
Sie können mit dem Attribut android:checked im Element <item> einen standardmäßigen angekreuzten Status für ein Element festlegen und ihn im Code mit der Methode setChecked() ändern.
Wenn ein auswählbares Element ausgewählt wird, ruft das System die entsprechende Callback-Methode 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 Optionsfelds nicht automatisch ändert. Sie können den aktuellen Status des Elements (so wie er vor der Auswahl durch den Nutzer war) mit isChecked() abfragen und den Status „checked“ dann mit setChecked() festlegen. Dies wird im folgenden Beispiel veranschaulicht:
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, behält die Aktivität den angekreuzten Status des Elements bei. Wenn der Nutzer das Menü später öffnet, ist der von Ihnen festgelegte angekreuzte Status sichtbar.
Menüpunkte basierend auf einem Intent hinzufügen
Manchmal soll ein Menüelement eine Aktivität über einen Intent starten, unabhängig davon, ob es sich um eine Aktivität in Ihrer App oder einer anderen App handelt. Wenn Sie den Intent kennen, den Sie verwenden möchten, und ein bestimmtes Menüelement haben, das den Intent initiiert, können Sie den Intent mit startActivity() in der entsprechenden Callback-Methode für die Auswahl von Elementen ausführen, z. B. im onOptionsItemSelected()-Callback.
Wenn Sie jedoch nicht sicher sind, ob auf dem Gerät des Nutzers eine App vorhanden ist, die den Intent verarbeitet, kann das Hinzufügen eines Menüelements, das ihn aufruft, zu einem nicht funktionierenden Menüelement führen, da der Intent möglicherweise nicht in eine Aktivität aufgelöst wird. Um dieses Problem zu beheben, können Sie in Android Menüelemente dynamisch zu Ihrem Menü hinzufügen, wenn Android Aktivitäten auf dem Gerät findet, die Ihren Intent verarbeiten.
So fügen Sie Menüelemente basierend auf verfügbaren Aktivitäten hinzu, die einen Intent akzeptieren:
- Definieren Sie eine Intention mit der Kategorie
CATEGORY_ALTERNATIVEoderCATEGORY_SELECTED_ALTERNATIVEoder beiden sowie allen anderen Anforderungen. - Rufe
Menu.addIntentOptions()an. Android sucht dann nach 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üpunkte 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 Intent-Filter mit dem definierten Intent bereitstellt, wird ein Menüelement hinzugefügt. Dabei wird der Wert im android:label des Intent-Filters als Titel des Menüelements und das App-Symbol als Symbol des Menüelements verwendet. Die Methode addIntentOptions() gibt die Anzahl der hinzugefügten Menüelemente zurück.
Aktivitäten in anderen Menüs hinzufügen
Sie können die Dienste Ihrer Aktivität anderen Apps anbieten, damit Ihre App in das Menü anderer Apps aufgenommen werden kann. Dadurch werden die zuvor beschriebenen Rollen umgekehrt.
Wenn Ihre App in anderen App-Menüs angezeigt werden soll, 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. 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.