Menu to typowy element interfejsu w wielu rodzajach aplikacji. Aby zapewnić użytkownikom spójne i spójne środowisko, używaj interfejsów API Menu
do prezentowania działań użytkowników i innych opcji w swoich działaniach.
Z tego dokumentu dowiesz się, jak na wszystkich wersjach Androida utworzyć trzy podstawowe typy menu lub prezentacji działań:
- Menu opcji i pasek aplikacji
- Menu opcji to podstawowy zbiór elementów menu dotyczących aktywności. To miejsce, w którym wykonujesz działania, które mają globalny wpływ na aplikację, takie jak „Wyszukiwarka”, „Napisz e-maila” i „Ustawienia”.
Zobacz sekcję Tworzenie menu opcji.
- Menu kontekstowe i tryb czynności kontekstowych
- Menu kontekstowe to pływające menu, które pojawia się, gdy użytkownik naciśnie i przytrzyma element. Podaje działania, które wpływają na wybraną treść lub ramkę kontekstu.
W trybie działań kontekstowych na pasku u góry ekranu wyświetlane są działania wpływające na wybrane treści. Użytkownik może wybrać wiele elementów.
Zobacz sekcję Tworzenie menu kontekstowego.
- Wyskakujące menu
- Wyskakujące menu zawiera pionową listę elementów zakotwiczonych w widoku, który je wywołuje. Warto utworzyć dodatkowe czynności, które odnoszą się do określonej treści, lub opcje dotyczące drugiej części polecenia. Działania w wyskakującym menu nie mają bezpośredniego wpływu na odpowiednie treści – służą do tego działania kontekstowe. Wyskakujące menu jest natomiast przeznaczone do rozszerzonych działań związanych z regionami treści w Twojej aktywności.
Zapoznaj się z sekcją Tworzenie wyskakującego menu.
Zdefiniuj menu w pliku XML
Dla wszystkich typów menu Android zapewnia standardowy format XML do definiowania pozycji menu. Zamiast tworzyć menu w kodzie aktywności, zdefiniuj menu i wszystkie jego elementy w zasobie menu XML. Następnie możesz powiększyć zasób menu, wczytać go jako obiekt Menu
, w swojej aktywności lub fragmencie.
Korzystanie z zasobu menu jest dobrym rozwiązaniem z tych powodów:
- Struktura menu jest łatwiejsza do przedstawienia w formacie XML.
- Oddziela on zawartość menu od kodu behawioralnego aplikacji.
- Pozwala tworzyć alternatywne konfiguracje menu dla różnych wersji platformy, rozmiarów ekranu i innych konfiguracji przy użyciu platformy zasobów aplikacji.
Aby zdefiniować menu, utwórz plik XML w katalogu res/menu/
projektu i utwórz menu z tymi elementami:
<menu>
- Definiuje element
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>
i<group>
. <item>
- Tworzy element
MenuItem
reprezentujący pojedynczy element menu. Ten element może zawierać zagnieżdżony element<menu>
służący do tworzenia podmenu. <group>
- Opcjonalny, niewidoczny kontener na elementy
<item>
. Pozwala dzielić pozycje menu na kategorie, aby miały wspólne właściwości, takie jak stan aktywności i widoczność. Więcej informacji znajdziesz w sekcji Tworzenie grupy menu.
Oto przykładowe 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żna użyć do określenia wyglądu i zachowania elementu. Pozycje w poprzednim menu
zawierają te atrybuty:
android:id
- Unikalny identyfikator zasobu dla danego elementu, dzięki któremu aplikacja może go rozpoznać, gdy użytkownik wybierze dany element.
android:icon
- Odwołanie do elementu rysowanego, który ma być używany jako ikona elementu.
android:title
- Odwołanie do ciągu znaków, które zostanie użyte jako tytuł elementu.
android:showAsAction
- Specyfikacja określająca, kiedy i jak dany element wyświetla się jako działanie na pasku aplikacji.
To najważniejsze atrybuty, których używasz, ale jest ich znacznie więcej. Informacje o wszystkich obsługiwanych atrybutach znajdziesz w dokumentacji zasobów menu.
Możesz dodać podmenu 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, takich jak elementy na pasku menu aplikacji na komputerze, takie jak Plik, Edytuj i Widok. 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 aktywności, _inflate_ wybierz zasób menu, przekonwertuj zasób XML na programowalny obiekt za pomocą funkcji MenuInflater.inflate()
.
W sekcjach poniżej znajdziesz informacje o tym, jak zwiększać rozmiar menu w przypadku każdego typu menu.
Utwórz menu opcji
Menu opcji, tak jak to pokazane na ilustracji 1, zawiera działania i inne opcje związane z bieżącym kontekstem aktywności, np. „Wyszukiwanie”, „Napisz e-maila” i „Ustawienia”.
![Ilustracja pokazująca pasek aplikacji Arkusze Google](https://developer.android.google.cn/static/images/training/appbar/appbar_sheets_2x.png?authuser=2&hl=pl)
Elementy w menu opcji możesz zadeklarować z poziomu podklasy Activity
lub podklasy Fragment
. Jeśli zarówno Twoja aktywność, jak i fragmenty deklarują elementy w menu opcji, elementy te będą połączone w interfejsie. Jako pierwsze pojawiają się elementy aktywności, a potem elementy dla każdego fragmentu w kolejności, w jakiej zostały one dodane do działania. W razie potrzeby możesz zmienić kolejność pozycji menu,
dodając atrybut android:orderInCategory
w każdym elemencie <item>
, który chcesz przenieść.
Aby określić menu opcji aktywności, zastąp parametr onCreateOptionsMenu()
.
Fragmenty kodu mają własne onCreateOptionsMenu()
wywołanie zwrotne. Ta metoda pozwala powiększyć zasób menu zdefiniowany w pliku XML do wartości Menu
podanej w wywołaniu zwrotnym. Widać to w tym przykładzie:
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ć pozycje menu za pomocą add()
i pobierać elementy za pomocą findItem()
, aby zmodyfikować 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 działania na pasku aplikacji, system wywoła metodę onOptionsItemSelected()
aktywności. Ta metoda przekazuje wybraną MenuItem
. Możesz wskazać ten element, wywołując metodę getItemId()
, która zwraca unikalny identyfikator pozycji menu zdefiniowany za pomocą atrybutu android:id
w zasobie menu lub za pomocą liczby całkowitej podanej w metodzie add()
. Możesz go dopasować do znanych pozycji menu, aby wykonać odpowiednie działanie.
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); } }
Gdy przejdziesz do pozycji menu, zwróć true
. Jeśli nie zajmujesz się tą pozycją menu, wywołaj implementację superklasy onOptionsItemSelected()
. Domyślna implementacja zwraca wartość „false” (fałsz).
Jeśli aktywność obejmuje fragmenty, system najpierw wywołuje onOptionsItemSelected()
dla aktywności, a następnie dla każdego fragmentu w kolejności ich dodania, aż jeden zwróci wartość true
lub wszystkie fragmenty.
Zmieniaj pozycje menu podczas działania
Gdy system wywoła funkcję onCreateOptionsMenu()
, zachowa wystąpienie wypełnionej przez Ciebie Menu
i nie wywoła ponownie onCreateOptionsMenu()
, chyba że menu zostanie unieważnione.
onCreateOptionsMenu()
należy jednak używać tylko do tworzenia początkowego stanu menu, a nie do wprowadzania zmian w trakcie cyklu życia działania.
Jeśli chcesz zmodyfikować menu opcji na podstawie zdarzeń występujących w cyklu życia aktywności, możesz to zrobić za pomocą metody onPrepareOptionsMenu()
. Ta metoda przekazuje Ci obiekt Menu
w obecnej postaci, aby umożliwić Ci jego modyfikowanie, np. przez dodanie, usunięcie lub wyłączenie elementów.
Fragmenty kodu zapewniają też
onPrepareOptionsMenu()
wywołanie zwrotne.
Menu opcji jest zawsze otwarte, gdy elementy menu znajdują się na pasku aplikacji. Gdy wystąpi zdarzenie i chcesz zaktualizować menu, wywołaj invalidateOptionsMenu()
, by zażądać wywołania systemowego onPrepareOptionsMenu()
.
Tworzenie menu kontekstowego
![Obraz przedstawiający pływające menu kontekstowe](https://developer.android.google.cn/static/develop/ui/views/images/context_menu_no_icons.png?authuser=2&hl=pl)
Menu kontekstowe oferuje działania, które wpływają na konkretny element lub ramkę kontekstową w interfejsie. Menu kontekstowe możesz podać dla dowolnego widoku, ale najczęściej używa się go w kolekcjach elementów RecylerView
lub innych widoków, w których użytkownik może wykonywać bezpośrednie działania na poszczególnych elementach.
Działania kontekstowe można udostępniać na 2 sposoby:
- w pływającym menu kontekstowym – Menu wyświetla się w postaci pływającej listy pozycji menu, podobnie jak w przypadku okna dialogowego, gdy użytkownik naciśnie i przytrzymasz widok, który deklaruje obsługę menu kontekstowego. Użytkownicy mogą wykonywać działania kontekstowe na jednym elemencie naraz.
- w trybie działań kontekstowych, Ten tryb jest implementacją systemową funkcji
ActionMode
, w której u góry ekranu wyświetla się pasek działań kontekstowych(CAB) z działaniami, które wpływają na wybrane elementy. Gdy ten tryb jest aktywny, użytkownicy mogą wykonywać działania na wielu elementach jednocześnie, jeśli aplikacja to obsługuje.
Uwaga: menu kontekstowe nie obsługuje skrótów elementów ani ikon elementów.
Tworzenie pływającego menu kontekstowego
Aby udostępnić pływające menu kontekstowe, wykonaj te czynności:
- Zarejestruj obiekt
View
, z którym powiązane jest menu kontekstowe, wywołującregisterForContextMenu()
i przekazując do niegoView
.Jeśli Twoja aktywność korzysta z elementu
RecyclerView
i chcesz, aby każda pozycja udostępniała to samo menu kontekstowe, zarejestruj wszystkie elementy w menu kontekstowym, przekazującRecyclerView
doregisterForContextMenu()
. - Zaimplementuj metodę
onCreateContextMenu()
wActivity
lubFragment
.Gdy zarejestrowany widok otrzyma zdarzenie naciśnięcia i przytrzymania, system wywoła metodę
onCreateContextMenu()
. W tym miejscu definiuje się elementy menu, zwykle przez poszerzenie 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
pozwala rozszerzyć menu kontekstowe z poziomu zasobu menu. Parametry metody wywołania zwrotnego obejmują obiektView
wybrany przez użytkownika i obiektContextMenu.ContextMenuInfo
, który zawiera dodatkowe informacje o wybranym elemencie. Jeśli Twoja aktywność ma kilka widoków, z których każdy zawiera inne menu kontekstowe, możesz użyć tych parametrów, aby określić, które menu kontekstowe należy zwiększyć. Wdróż
onContextItemSelected()
zgodnie z poniższym przykładem. Gdy użytkownik wybiera pozycję w menu, system wywołuje tę metodę, by umożliwić Ci 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żdej pozycji menu w pliku XML za pomocą atrybutuandroid:id
, jak pokazano w sekcji Definiowanie menu w pliku XML.Gdy przejdziesz do pozycji menu, zwróć
true
. Jeśli nie obsługujesz tej pozycji menu, przekaż ją do implementacji klasy nadrzędnej. Jeśli aktywność zawiera fragmenty, najpierw otrzymuje to wywołanie zwrotne. Po wywołaniu nieobsługiwanej klasy superklasy system przekazuje zdarzenie do odpowiedniej metody wywołania zwrotnego w każdym fragmencie, po kolei, w kolejności dodawania fragmentów, aż do zwrócenia wartościtrue
lubfalse
. Domyślne implementacjeActivity
iandroid.app.Fragment
zwracająfalse
, więc zawsze wywołaj klasę nadrzędną, gdy nie jest obsługiwana.
Użyj trybu czynności kontekstowej
Tryb działań kontekstowych to implementacja systemowa ActionMode
, która koncentruje 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 pokazujący działania, które użytkownik może wykonać na wybranych elementach. Gdy ten tryb jest włączony, użytkownik może zaznaczyć wiele elementów (o ile aplikacja obsługuje tę funkcję) i odznaczać je, aby kontynuować nawigowanie w obrębie aktywności. Tryb działań jest wyłączony, a pasek działań kontekstowych znika, gdy użytkownik odznaczy wszystkie elementy, kliknie przycisk Wstecz lub kliknie działanie Gotowe z lewej strony paska.
W przypadku widoków z działaniami kontekstowymi tryb działań kontekstowych jest zwykle wywoływany, gdy wystąpi co najmniej jedno z tych 2 zdarzeń:
- Użytkownik klika i przytrzymuje widok.
- Użytkownik zaznacza pole wyboru lub podobny komponent interfejsu w widoku.
Sposób, w jaki aplikacja wywołuje tryb działania kontekstowego i określa działanie każdego działania, zależy od projektu. Są 2 wzory:
- Dla działań kontekstowych dotyczących poszczególnych, dowolnych widoków.
- W przypadku zbiorczych działań kontekstowych dotyczących grup elementów w elemencie
RecyclerView
, które umożliwiają użytkownikowi wybranie wielu elementów i wykonanie na nich działania.
W sekcjach poniżej opisano konfigurację wymaganą w każdym scenariuszu.
Włącz tryb działań kontekstowych w poszczególnych widokach
Jeśli chcesz wywoływać tryb działania kontekstowego tylko wtedy, gdy użytkownik wybierze określone widoki, wykonaj te czynności:
- Zaimplementuj interfejs
ActionMode.Callback
zgodnie z poniższym przykładem. W jego metodach wywołania zwrotnego możesz określić działania dla kontekstowego paska działań, odpowiadać na zdarzenia kliknięcia dotyczące działań oraz obsługiwać inne zdarzenia cyklu życia dla 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 wywołania zwrotne zdarzeń są prawie takie same jak wywołania zwrotne menu opcji z tą różnicą, że każda z nich przekazuje również obiekt
ActionMode
powiązany ze zdarzeniem. Za pomocą interfejsów APIActionMode
możesz wprowadzać różne zmiany w CAB, na przykład zmieniać tytuł i podtytuł za pomocą właściwościsetTitle()
isetSubtitle()
, co jest przydatne do określania liczby wybranych elementów.Poprzedni przykład ustawia zmienną
actionMode
nanull
po zniszczeniu trybu działania. W następnym kroku zobaczysz, jak jest inicjowana i jak może pomóc zapisanie zmiennej członkowskiej w aktywności lub fragmencie. - Wywołaj
startActionMode()
, gdy chcesz wyświetlić pasek, na przykład gdy użytkownik naciśnie i przytrzymasz 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łujesz
startActionMode()
, system zwraca utworzony elementActionMode
. Dzięki zapisaniu go w zmiennej użytkownika możesz wprowadzać zmiany na kontekstowym pasku działań w odpowiedzi na inne zdarzenia. W poprzednim przykładzie używamyActionMode
, aby zagwarantować, że instancjaActionMode
nie zostanie odtworzona, jeśli jest już aktywna. Aby to zrobić, przed uruchomieniem trybu działania sprawdź, czy element ma wartość null.
Utwórz wyskakujące menu
![Obraz przedstawiający wyskakujące menu w aplikacji Gmail zakotwiczone do rozszerzonego przycisku w prawym górnym rogu.](https://developer.android.google.cn/static/images/ui/popupmenu.png?authuser=2&hl=pl)
PopupMenu
to menu modalne zakotwiczone na elemencie View
. Pojawia się pod widokiem zakotwiczonym,
jeśli jest wystarczająco dużo miejsca, lub nad widokiem, jeśli nie jest widoczny. Jest to przydatne,
gdy:
- Udostępnianie rozszerzonego menu dla działań odnoszących się do określonych treści, takich jak nagłówki e-maili w Gmailu, jak pokazano na rys. 4.
- dodanie drugiej części zdania polecenia, na przykład przycisku Dodaj, który powoduje wyświetlenie menu z różnymi opcjami Dodaj.
- Udostępnij menu podobne do elementu
Spinner
, które nie zawiera trwałego wyboru.
Jeśli zdefiniujesz menu w formacie XML, wyświetli się ono w ten sposób:
- Utwórz instancję
PopupMenu
za pomocą konstruktora, który pobiera bieżącą aplikacjęContext
iView
, z którym zakotwiczone jest menu. - Użyj polecenia
MenuInflater
, aby rozszerzyć zasób menu do obiektuMenu
zwróconego przez funkcjęPopupMenu.getMenu()
. - Będziesz dzwonić pod numer
PopupMenu.show()
.
Oto przykład:
<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" />
Działanie może wtedy wyświetlić wyskakujące menu:
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 jest zamykane, gdy użytkownik wybierze pozycję lub kliknie poza obszarem menu. Możesz nasłuchiwać zdarzenia odrzucenia za pomocą PopupMenu.OnDismissListener
.
Obsługa zdarzeń kliknięcia
Aby wykonać działanie, gdy użytkownik wybierze pozycję menu, zaimplementuj interfejs PopupMenu.OnMenuItemClickListener
i zarejestruj go w PopupMenu
, wywołując setOnMenuItemclickListener()
.
Gdy użytkownik wybiera element, system wywołuje wywołanie zwrotne onMenuItemClick()
w interfejsie.
Widać to w tym przykładzie:
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; } }
Utwórz grupę menu
Grupa menu to zbiór pozycji menu, które mają wspólne cechy. Dzięki grupie możesz:
- Pokaż lub ukryj wszystkie elementy za pomocą właściwości
setGroupVisible()
. - Włącz lub wyłącz wszystkie elementy za pomocą parametru
setGroupEnabled()
. - Określ, czy wszystkie elementy można zaznaczyć za pomocą
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ą elementami potocznymi. Możesz jednak modyfikować cechy 2 elementów w grupie, odwołując się do identyfikatora grupy i używając poprzednich metod. System nigdy nie rozdziela też zgrupowanych elementów. Jeśli na przykład zadeklarujesz android:showAsAction="ifRoom"
dla każdego elementu, oba te elementy pojawią się na pasku działań lub oba w obszarze działań.
Używaj pozycji menu, które można zaznaczyć
Menu może służyć jako interfejs do włączania i wyłączania opcji, a także za pomocą pól wyboru dla samodzielnych opcji lub przycisków dla grup opcji wzajemnie wykluczających się. Rysunek 5 przedstawia menu podrzędne z elementami, które można zaznaczyć za pomocą opcji.
Zachowanie, które można sprawdzić w przypadku poszczególnych pozycji menu, możesz określić 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 pozycje w tej grupie menu można zaznaczyć za pomocą 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 jeden z tych atrybutów:
single
- Można zaznaczyć tylko jeden element z grupy, co spowoduje utworzenie przycisków.
all
- Można zaznaczyć wszystkie elementy, co spowoduje wyświetlenie pól wyboru.
none
- Brak elementów do sprawdzenia.
Możesz zastosować do elementu domyślnie zaznaczony stan „zaznaczony” za pomocą atrybutu android:checked
w elemencie <item>
i zmienić go w kodzie za pomocą metody setChecked()
.
Po zaznaczeniu elementu, który można zaznaczyć, system wywołuje odpowiednią metodę wywołania zwrotnego wybranego elementu, na przykład onOptionsItemSelected()
.
W tym miejscu ustawia się stan pola wyboru, ponieważ jego stan nie zmienia się automatycznie. Możesz przesłać zapytanie o bieżący stan elementu (w postaci, w jakiej był przed wybraniem go przez użytkownika), za pomocą funkcji isChecked()
, a następnie ustawić stan zaznaczonego za pomocą setChecked()
. W tym przykładzie widać:
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, jego widoczność nie zmieni się, gdy użytkownik wybierze pole wyboru. Gdy ustawisz stan, działanie to zachowuje zaznaczony stan elementu, dzięki czemu, gdy użytkownik otworzy menu później, ustawiony przez Ciebie stan będzie widoczny.
Dodaj pozycje menu na podstawie intencji
Czasem chcesz, aby pozycja menu uruchamiała działanie za pomocą polecenia Intent
, niezależnie od tego, czy jest to działanie w Twojej aplikacji czy w innej. Jeśli wiesz, czego chcesz użyć, i masz określony element menu, który inicjuje intencję, możesz wykonać intencję za pomocą metody startActivity()
w ramach odpowiedniej metody wywołania zwrotnego wybranego elementu, na przykład wywołania zwrotnego onOptionsItemSelected()
.
Jeśli jednak nie masz pewności, czy na urządzeniu użytkownika znajduje się aplikacja, która obsługuje intencję, dodanie pozycji menu, która je wywołuje, może spowodować, że pozycja menu nie będzie działać, ponieważ intencja może nie odpowiadać działaniu. Aby rozwiązać ten problem, Android umożliwia dynamiczne dodawanie pozycji menu do menu, gdy znajdzie na urządzeniu działania, które obsługują Twoje intencje.
Aby dodać pozycje menu na podstawie dostępnych działań, które akceptują intencję, wykonaj te czynności:
- Zdefiniuj intencję za pomocą kategorii
CATEGORY_ALTERNATIVE
lubCATEGORY_SELECTED_ALTERNATIVE
bądź obu tych elementów, i dodaj inne wymagania. - Zadzwoń pod numer
Menu.addIntentOptions()
. Android wyszukuje wtedy aplikacje, które mogą to zrobić, i dodaje je do menu.
Jeśli nie masz zainstalowanych aplikacji, które spełniałyby tę intencję, elementy menu nie są dodawane.
Widać to w tym przykładzie:
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żdego znalezionego działania, które dostarcza filtr intencji pasujący do zdefiniowanej intencji, pojawia się element menu, w którym wartość w filtrze intencji (android:label
) jest używana jako tytuł, a ikona aplikacji jako ikona elementu menu. Metoda addIntentOptions()
zwraca liczbę dodanych pozycji menu.
Pozwól na dodawanie aktywności do innych menu
Możesz oferować innym aplikacjom usługi związane z aktywnością, dzięki czemu Twoja aplikacja będzie widoczna w menu innych osób – odwrotnie będzie w przypadku opisanych wcześniej ról.
Aby znaleźć się w innych menu aplikacji, zdefiniuj filtr intencji w zwykły sposób, ale w przypadku kategorii filtra intencji uwzględnij wartość CATEGORY_ALTERNATIVE
lub CATEGORY_SELECTED_ALTERNATIVE
albo obie te wartości. Widać to w tym przykładzie:
<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.