Menu to element interfejsu użytkownika, który występuje w wielu typach aplikacji. Aby zapewnić użytkownikom znajome i spójne wrażenia, używaj interfejsów API Menu
do przedstawiania działań użytkowników i innych opcji w swoich aktywnościach.
W tym dokumencie wyjaśniamy, jak utworzyć 3 podstawowe typy menu lub interakcji we wszystkich wersjach Androida:
- Menu opcji i pasek aplikacji
- Menu opcji to główna kolekcja pozycji menu aktywności. To miejsce, w którym umieszczasz działania mające globalny wpływ na aplikację, takie jak „Szukaj”, „Napisz e-maila” i „Ustawienia”.
Przeczytaj sekcję Tworzenie menu opcji.
- Menu kontekstowe i tryb czynności kontekstowej
- Menu kontekstowe to menu pływające, które pojawia się, gdy użytkownik dotyka i przytrzymuje dany element. Zawiera działania, które wpływają na wybrane treści lub ramkę kontekstową.
Tryb działań kontekstowych wyświetla elementy działań, które wpływają na wybrane treści, na pasku u góry ekranu, oraz umożliwia użytkownikowi wybranie wielu elementów.
Zapoznaj się z sekcją Tworzenie menu kontekstowego.
- Menu kontekstowe
- Menu wyskakujące zawiera listę elementów wyświetlaną pionowo i zablokowaną w widoku, z którego wywołano menu. Jest to przydatne, gdy chcesz wyświetlić więcej działań związanych z określonymi treściami lub gdy chcesz wyświetlić opcje w drugiej części polecenia. Czynności w menu wyskakującym nie wpływają bezpośrednio na odpowiadające im treści – do tego służą działania kontekstowe. Menu to służy do rozszerzonych działań związanych z regionami treści w Twojej aktywności.
Przeczytaj sekcję Tworzenie menu podręcznego.
Definiowanie menu w formacie XML
W przypadku wszystkich typów menu Android udostępnia standardowy format XML do definiowania elementów menu. Zamiast tworzyć menu w kodzie aktywności, zdefiniuj menu i wszystkie jego elementy w zasobach menu XML. Następnie możesz napompować zasób menu, wczytując go jako obiekt Menu
w swojej aktywności lub fragmencie.
Korzystanie z menu jest dobrym rozwiązaniem z tych powodów:
- Łatwiej jest wizualizować strukturę menu w formacie XML.
- oddziela zawartość menu od kodu aplikacji,
- Umożliwia tworzenie alternatywnych konfiguracji menu dla różnych wersji platformy, rozmiarów ekranu i innych konfiguracji za pomocą frameworku zasobów aplikacji.
Aby zdefiniować menu, utwórz plik XML w katalogu res/menu/
projektu i utwórz menu za pomocą tych elementów:
<menu>
- Określa
Menu
, który jest kontenerem dla pozycji menu. Element<menu>
musi być węzłem głównym pliku i może zawierać co najmniej 1 element<item>
lub<group>
. <item>
- Tworzy element
MenuItem
, który reprezentuje pojedynczy element menu. Ten element może zawierać zagnieżdżony element<menu>
, aby utworzyć menu podrzędne. <group>
- Opcjonalny, niewidoczny kontener dla elementów
<item>
. Umożliwia kategoryzowanie elementów menu, dzięki czemu mają one wspólne właściwości, takie jak stan aktywny i widoczność. Więcej informacji znajdziesz w sekcji Tworzenie grupy menu.
Oto przykład menu o nazwie 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>
Element <item>
obsługuje kilka atrybutów, których możesz używać do definiowania wyglądu i działania elementu. Elementy w menu powyżej mają te atrybuty:
android:id
- Identyfikator zasobu, który jest unikalny dla danego elementu i pozwala aplikacji rozpoznać go, gdy użytkownik go wybierze.
android:icon
- Odwoływanie się do pliku drawable, który ma być używany jako ikona elementu.
android:title
- Odwołanie do ciągu znaków, który ma być użyty jako tytuł elementu.
android:showAsAction
- Specyfikacja dotycząca tego, kiedy i jak ten element ma się wyświetlać jako element działania na pasku aplikacji.
To najważniejsze atrybuty, których używasz, ale dostępnych jest ich znacznie więcej. Informacje o wszystkich obsługiwanych atrybutach znajdziesz w dokumentacji Zasoby menu.
Możesz dodać menu podrzędne do elementu w dowolnym menu, dodając element <menu>
jako element podrzędny elementu <item>
.
Menu podrzędne są przydatne, gdy aplikacja ma wiele funkcji, które można uporządkować według tematów, np. elementy na pasku menu aplikacji na komputerze, takie jak Plik, Edytuj i Wyświetl. Zobacz ten przykład:
<?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>
Aby użyć menu w swojej aktywności, _rozwiń_ zasób menu, przekształcając zasób XML w programowalny obiekt za pomocą funkcji MenuInflater.inflate()
.
W sekcjach poniżej wyjaśniamy, jak wczytywać menu w przypadku każdego typu menu.
Tworzenie menu opcji
W menu opcji, takim jak pokazane na rysunku 1, możesz uwzględnić działania i inne opcje, które są istotne w kontekście bieżącej aktywności, takie jak „Szukaj”, „Napisz e-maila” i „Ustawienia”.
![Obraz pokazujący pasek aplikacji Arkuszy Google](https://developer.android.google.cn/static/images/training/appbar/appbar_sheets_2x.png?authuser=3&hl=pl)
Elementy menu opcji możesz zadeklarować w podklasie Activity
lub Fragment
. Jeśli zarówno aktywność, jak i fragmenty deklarują elementy menu opcji, elementy te są łączone w interfejsie. Najpierw pojawiają się elementy aktywności, a potem elementy każdego fragmentu w kolejności, w jakiej zostały dodane do aktywności. W razie potrzeby możesz zmienić kolejność pozycji w menu za pomocą atrybutu android:orderInCategory
w każdym <item>
, który chcesz przenieść.
Aby określić menu opcji dla aktywności, zastąpij wartość onCreateOptionsMenu()
.
Fragmenty mają własne wywołania funkcjionCreateOptionsMenu()
. W ramach tej metody możesz napełnić zasób menu zdefiniowany w pliku XML do obiektu Menu
podanego w funkcji wywołania zwrotnego. Przykład:
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; }
Możesz też dodawać elementy menu za pomocą interfejsu add()
i pobierać elementy za pomocą interfejsu findItem()
, aby poprawiać ich właściwości za pomocą interfejsów API MenuItem
.
Obsługa zdarzeń kliknięcia
Gdy użytkownik wybierze element z menu opcji, w tym elementy działania na pasku aplikacji, system wywołuje metodę onOptionsItemSelected()
Twojej aktywności. Ta metoda przekazuje wybrany element MenuItem
. Możesz zidentyfikować element, wywołując metodę getItemId()
, która zwraca unikalny identyfikator elementu menu zdefiniowany przez atrybut android:id
w zasobie menu lub za pomocą liczby całkowitej przekazanej do metody add()
. Aby wykonać odpowiednie działanie, możesz dopasować ten identyfikator do znanych elementów menu.
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); } }
Po pomyślnym obsłudze elementu menu zwróć true
. Jeśli nie obsługujesz elementu menu, wywołaj implementację klasy nadrzędnej onOptionsItemSelected()
. Domyślna implementacja zwraca wartość false.
Jeśli Twoja aktywność zawiera fragmenty, system najpierw wywołuje funkcję onOptionsItemSelected()
dla tej aktywności, a potem dla każdego fragmentu w kolejności dodawania fragmentów, aż do momentu, gdy zostanie zwrócona wartość true
lub wywołane wszystkie fragmenty.
Zmiana pozycji menu w czasie wykonywania
Gdy system wywoła funkcję onCreateOptionsMenu()
, zatrzymuje instancję wypełnionego przez Ciebie obiektu Menu
i nie wywołuje go ponownie, chyba że menu zostanie unieważnione.onCreateOptionsMenu()
Użyj jednak elementu onCreateOptionsMenu()
tylko do utworzenia początkowego stanu menu, a nie do wprowadzania zmian w trakcie cyklu życia aktywności.
Jeśli chcesz zmodyfikować menu opcji na podstawie zdarzeń występujących w cyklu życia aktywności, możesz to zrobić w metodzie onPrepareOptionsMenu()
. Ta metoda przekazuje obiekt Menu
w jego bieżącej postaci, dzięki czemu możesz go modyfikować, np. dodając, usuwając lub wyłączając elementy.
Fragmenty zawierają też funkcję onPrepareOptionsMenu()
wywołania zwrotnego.
Menu opcji jest zawsze otwarte, gdy elementy menu są wyświetlane na pasku aplikacji. Gdy wystąpi zdarzenie i chcesz zaktualizować menu, wywołaj funkcję invalidateOptionsMenu()
, aby system wykonał wywołanie onPrepareOptionsMenu()
.
Tworzenie menu kontekstowego
![Obraz pokazujący pływające menu kontekstowe](https://developer.android.google.cn/static/develop/ui/views/images/context_menu_no_icons.png?authuser=3&hl=pl)
Menu kontekstowe zawiera działania, które wpływają na konkretny element lub kontekst w interfejsie. Menu kontekstowe możesz udostępnić w przypadku dowolnego widoku, ale najczęściej są one używane w przypadku elementów w widoku RecylerView
lub innych kolekcjach widoków, w których użytkownik może wykonywać bezpośrednie działania dotyczące poszczególnych elementów.
Działania kontekstowe możesz udostępniać na 2 sposoby:
- W menu kontekstowym. Menu wyświetla się jako lista elementów menu, podobnie jak okno dialogowe, gdy użytkownik dotyka i trzyma widok, który deklaruje obsługę menu kontekstowego. Użytkownicy mogą wykonywać działania kontekstowe dotyczące tylko jednego elementu naraz.
- W trybie czynności kontekstowej. Jest to systemowa implementacja
ActionMode
, która wyświetla u góry ekranu kontekstualny pasek działań(CAB) z elementami działań wpływającymi na wybrane elementy. Gdy ten tryb jest aktywny, użytkownicy mogą wykonywać czynności na wielu elementach jednocześnie (jeśli aplikacja to umożliwia).
Uwaga: menu kontekstowe nie obsługują skrótów ani ikon elementów.
Tworzenie pływającego menu kontekstowego
Aby wyświetlić pływające menu kontekstowe:
- Zarejestruj
View
, z którym powiązane jest menu kontekstowe, wywołując funkcjęregisterForContextMenu()
i przekazując jej argumentView
.Jeśli Twoja aktywność używa elementu
RecyclerView
i chcesz, aby każdy element wyświetlał to samo menu kontekstowe, zarejestruj wszystkie elementy w menu kontekstowym, przekazując elementRecyclerView
do elementuregisterForContextMenu()
. - Zaimplementuj metodę
onCreateContextMenu()
wActivity
lubFragment
.Gdy zarejestrowany widok otrzyma zdarzenie dotknij i przytrzymaj, system wywoła metodę
onCreateContextMenu()
. Tutaj definiujesz elementy menu, zwykle przez wczytywanie zasobu menu, jak w tym przykładzie: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); }
MenuInflater
umożliwia napełnianie menu kontekstowego z zasobu menu. Parametry metody wywołania zwrotnego toView
wybrany przez użytkownika oraz obiektContextMenu.ContextMenuInfo
, który zawiera dodatkowe informacje o wybranym elemencie. Jeśli Twoja aktywność ma kilka widoków, z których każdy ma inne menu kontekstowe, możesz użyć tych parametrów, aby określić, które menu kontekstowe ma się wyświetlić. Wprowadź
onContextItemSelected()
, jak pokazano w tym przykładzie. Gdy użytkownik wybierze element menu, system wywoła tę metodę, aby umożliwić wykonanie odpowiedniej czynności.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); } }
Metoda
getItemId()
wysyła zapytanie o identyfikator wybranego elementu menu, który przypisujesz do każdego elementu menu w pliku XML za pomocą atrybutuandroid:id
, jak pokazano w sekcji Definiowanie menu w pliku XML.Po pomyślnym obsłudze elementu menu zwróć
true
. Jeśli nie obsługujesz pozycji menu, przekaż ją do implementacji klasy nadrzędnej. Jeśli aktywność zawiera fragmenty, najpierw otrzyma to wywołanie zwrotne. Gdy wywołuje się nadrzędną klasę w przypadku nieobsługiwanych zdarzeń, system przekazuje zdarzenie do odpowiedniej metody wywołania zwrotnego w każdym fragmencie, po kolei, w kolejności dodawania poszczególnych fragmentów, aż do momentu zwrócenia wartościtrue
lubfalse
. Domyślne implementacje funkcjiActivity
iandroid.app.Fragment
zwracająfalse
, więc w przypadku braku obsługi zawsze wywołuj metodę nadrzędną.
Korzystanie z trybu czynności kontekstowej
Tryb działania kontekstowego to implementacja systemu ActionMode
, która skupia interakcje użytkownika na wykonywaniu działań kontekstowych. Gdy użytkownik włączy ten tryb, wybierając element, u góry ekranu pojawi się pasek działań kontekstowych z działaniami, które może wykonać na wybranych elementach. Gdy ten tryb jest włączony, użytkownik może wybrać wiele elementów (jeśli aplikacja to umożliwia), a także odznaczyć wybrane elementy i kontynuować nawigację w ramach aktywności. Tryb działania jest wyłączony, a pasek działań kontekstowych znika, gdy użytkownik deaktywuje wszystkie elementy, kliknie przycisk Wstecz lub kliknie Gotowe po lewej stronie paska.
W przypadku widoków, które umożliwiają wykonywanie czynności kontekstowych, tryb czynności kontekstowych jest zwykle wywoływany, gdy wystąpi jedno z tych zdarzeń:
- Użytkownik dotyka i przytrzymuje widok.
- Użytkownik zaznacza pole wyboru lub podobny element interfejsu w danym widoku.
Sposób wywoływania przez aplikację trybu działania kontekstowego i definiowania zachowania dla każdego działania zależy od projektu aplikacji. Dostępne są 2 wersje:
- Do działań kontekstowych w przypadku pojedynczych, dowolnych wyświetleń.
- Do wykonywania zbiorczych działań kontekstowych na grupach elementów w
RecyclerView
, aby umożliwić użytkownikowi wybranie wielu elementów i wykonanie działania na wszystkich z nich.
W kolejnych sekcjach opisano konfigurację wymaganą w pierwszym scenariuszu.
Włączanie trybu czynności kontekstowej w przypadku poszczególnych wyświetleń
Jeśli chcesz wywołać tryb czynności kontekstowej tylko wtedy, gdy użytkownik wybierze określone widoki, wykonaj te czynności:
- Zaimplementuj interfejs
ActionMode.Callback
w sposób pokazany w tym przykładzie. W metodach wywołania możesz określić działania dla kontekstulnego paska działań, reagować na zdarzenia kliknięcia elementów działań oraz obsługiwać inne zdarzenia cyklu życia w przypadku trybu działania.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; } };
Te funkcje zwracane przez zdarzenia są prawie identyczne jak funkcje zwracane przez menu opcji, z tą różnicą, że każda z nich przekazuje też obiekt
ActionMode
powiązany ze zdarzeniem. Za pomocą interfejsów APIActionMode
możesz wprowadzać różne zmiany w pliku CAB, np. poprawiać tytuł i podtytuł za pomocą interfejsówsetTitle()
isetSubtitle()
, co jest przydatne do wskazywania liczby wybranych elementów.W tym przykładzie po zniszczeniu trybu działania zmienna
actionMode
przyjmuje wartośćnull
. W następnym kroku zobacz, jak jest inicjowana i jak zapisywanie zmiennej członkowskiej w aktywności lub fragmencie może być przydatne. - Wywołaj metodę
startActionMode()
, gdy chcesz wyświetlić pasek, na przykład gdy użytkownik dotyka i przytrzymuje widok.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; } });
Gdy wywołasz funkcję
startActionMode()
, system zwraca utworzony obiektActionMode
. Zapisując go w zmiennej członkowskiej, możesz wprowadzać zmiany w pasku działań kontekstowych w odpowiedzi na inne zdarzenia. W poprzednim przykładzie funkcjaActionMode
jest używana, aby nie tworzyć ponownie instancjiActionMode
, jeśli jest ona już aktywna. Przed rozpoczęciem działania sprawdzana jest wartość nullowa elementu.
Tworzenie menu wyskakującego
![Obraz pokazujący menu wyskakujące w aplikacji Gmail, zakotwiczone w prawym górnym rogu przy przycisku menu.](https://developer.android.google.cn/static/images/ui/popupmenu.png?authuser=3&hl=pl)
PopupMenu
to menu modalne zakotwiczone w elementach View
. Jeśli jest miejsce, pojawia się pod widokiem kotwicy, w przeciwnym razie – nad nim. Jest ona przydatna do:
- Dodanie menu przepełnienia dla działań, które dotyczą konkretnych treści, takich jak nagłówki e-maili w Gmailu (patrz rysunek 4).
- Podanie drugiej części zdania z poleceniem, np. przycisk oznaczony jako Dodaj, który powoduje wyświetlenie menu z różnymi opcjami Dodaj.
- udostępnianie menu podobnego do menu
Spinner
, które nie zachowuje trwałego wyboru.
Jeśli menu jest zdefiniowane w pliku XML, możesz wyświetlić menu wyskakujące w ten sposób:
- Utwórz instancję
PopupMenu
za pomocą konstruktora, który przyjmuje bieżącą aplikacjęContext
iView
, do której jest zakotwiczone menu. - Użyj funkcji
MenuInflater
, aby wczytać zasób menu do obiektuMenu
zwracanego przez funkcjęPopupMenu.getMenu()
. - Będziesz dzwonić pod numer
PopupMenu.show()
.
Oto przykład przycisku, który otwiera menu:
<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" />
W ramach tej aktywności może wyświetlić się menu podobne do tego:
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(); });
Menu zostaje zamknięte, gdy użytkownik wybierze element lub kliknie poza obszarem menu. Zdarzenie dismiss możesz nasłuchiwać za pomocą funkcji PopupMenu.OnDismissListener
.
Obsługa zdarzeń kliknięcia
Aby wykonać działanie po wybraniu przez użytkownika elementu menu, zaimplementuj interfejs PopupMenu.OnMenuItemClickListener
i zarejestruj go w PopupMenu
, wywołując funkcję setOnMenuItemclickListener()
.
Gdy użytkownik wybierze element, system wywoła w Twoim interfejsie funkcję onMenuItemClick()
.
Przykład:
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; } }
Tworzenie grupy menu
Grupa menu to zbiór pozycji menu o wspólnych cechach. Dzięki grupie możesz:
- Wyświetlanie lub ukrywanie wszystkich elementów za pomocą przycisku
setGroupVisible()
. - Włącz lub wyłącz wszystkie elementy, używając opcji
setGroupEnabled()
. - Określ, czy wszystkie elementy są zaznaczane za pomocą opcji
setGroupCheckable()
.
Grupę możesz utworzyć, zagnieżdżając elementy <item>
w elemencie <group>
w zasobie menu lub podając identyfikator grupy za pomocą metody add()
.
Oto przykład zasobu menu zawierającego grupę:
<?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>
Elementy w grupie są wyświetlane na tym samym poziomie co pierwszy element – wszystkie 3 elementy w menu są sobie równe. Możesz jednak zmodyfikować cechy 2 elementów w grupie, podając identyfikator grupy i korzystając z poprzednich metod. System nigdy nie rozdziela też elementów zgrupowanych. Jeśli na przykład deklarujesz android:showAsAction="ifRoom"
dla każdego elementu, oba te elementy będą widoczne na pasku czynności lub w menu czynności.
Używanie pozycji menu z opcją zaznaczenia
Menu może być przydatne jako interfejs do włączania i wyłączania opcji. Możesz użyć pola wyboru dla opcji samodzielnych lub przycisków opcji dla grup opcji wzajemnie się wykluczających. Rysunek 5 przedstawia menu podrzędne z elementami, które można zaznaczyć za pomocą opcji.
Zachowanie związane z opcją wyboru możesz zdefiniować dla poszczególnych elementów menu za pomocą atrybutu android:checkable
w elemencie <item>
lub dla całej grupy za pomocą atrybutu android:checkableBehavior
w elemencie <group>
. Na przykład wszystkie elementy w tej grupie menu można zaznaczyć za pomocą przycisku opcji:
<?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>
Atrybut android:checkableBehavior
akceptuje jedną z tych wartości:
single
- Tylko jeden element z grupy może być zaznaczony, co powoduje użycie przycisków wyboru.
all
- Wszystkie elementy mogą być zaznaczone, co powoduje pojawienie się pól wyboru.
none
- Brak elementów do zaznaczenia.
Możesz zastosować domyślny stan zaznaczonego elementu za pomocą atrybutu android:checked
w elemencie <item>
i zmienić go w kodzie za pomocą metody setChecked()
.
Gdy wybrany zostanie element, który można zaznaczyć, system wywołuje odpowiednią metodę wywołania po wybraniu elementu, np. onOptionsItemSelected()
.
Tutaj ustawiasz stan pola wyboru, ponieważ pole wyboru lub przycisk radiowy nie zmienia swojego stanu automatycznie. Za pomocą zapytania isChecked()
możesz sprawdzić bieżący stan elementu (taki, jaki był przed jego wybraniem przez użytkownika), a za pomocą zapytania setChecked()
możesz ustawić stan wybrany (checked). Przykład:
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); } }
Jeśli nie ustawisz stanu zaznaczonego w ten sposób, widoczny stan pola wyboru lub przycisku opcji nie zmieni się, gdy użytkownik go wybierze. Gdy ustawisz stan, aktywność zachowa zaznaczony stan elementu, dzięki czemu gdy użytkownik otworzy menu, zaznaczony stan będzie widoczny.
Dodawanie pozycji menu na podstawie zamiaru
Czasami chcesz, aby element menu uruchamiał działanie za pomocą funkcji Intent
, niezależnie od tego, czy jest to działanie w Twojej aplikacji czy innej aplikacji. Gdy znasz intencję, której chcesz użyć, i masz konkretny element menu, który ją inicjuje, możesz ją wykonać za pomocą funkcji Intent
w ramach odpowiedniej metody wywołania po wybraniu elementu, np. wywołania onOptionsItemSelected()
.startActivity()
Jeśli jednak nie masz pewności, czy na urządzeniu użytkownika jest aplikacja, która obsługuje ten zamiar, dodanie elementu menu, który go wywołuje, może spowodować, że element menu nie będzie działać, ponieważ zamiar może nie zostać przekształcony w działanie. Aby rozwiązać ten problem, Android umożliwia dynamiczne dodawanie pozycji menu do menu, gdy wykryje na urządzeniu działania, które obsługują Twój zamiar.
Aby dodać pozycje menu na podstawie dostępnych działań, które akceptują intencję, wykonaj te czynności:
- Określ intencję za pomocą kategorii
CATEGORY_ALTERNATIVE
lubCATEGORY_SELECTED_ALTERNATIVE
albo obu tych kategorii oraz innych wymagań. - Zadzwoń pod numer
Menu.addIntentOptions()
. Następnie Android wyszukuje aplikacje, które mogą wykonać daną intencję, i dodaje je do menu.
Jeśli nie ma zainstalowanych aplikacji, które spełniają intencję, żadne elementy menu nie są dodawane.
Przykład:
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; }
W przypadku każdej znalezionej aktywności, która zawiera filtr intencji pasujący do zdefiniowanej intencji, dodawany jest element menu. Wartość w polu android:label
filtra intencji jest używana jako tytuł elementu menu, a ikona aplikacji jako ikona elementu menu. Metoda addIntentOptions()
zwraca liczbę dodanych pozycji menu.
zezwalanie na dodawanie Twojej aktywności do innych menu.
Możesz oferować usługi swojej aktywności innym aplikacjom, aby Twoja aplikacja mogła być uwzględniona w menu innych aplikacji – odwrócenie opisanych wcześniej ról.
Aby uwzględnić aplikację w innych menu aplikacji, zdefiniuj filtr intencji w zwykły sposób, ale w kategorii filtra intencji uwzględnij wartości CATEGORY_ALTERNATIVE
lub CATEGORY_SELECTED_ALTERNATIVE
albo obie. Przykład:
<intent-filter label="@string/resize_image"> ... <category android:name="android.intent.category.ALTERNATIVE" /> <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> ... </intent-filter>
Więcej informacji o tworzeniu filtrów intencji znajdziesz w artykule Intencje i filtry intencji.