Menu to powszechny element interfejsu w wielu typach aplikacji. Aby zapewnić użytkownikom dostęp do znanych i spójnych funkcji, wykorzystaj interfejsy API Menu
do prezentowania działań użytkowników i innych opcji w swoich działaniach.
W tym dokumencie opisujemy, jak tworzyć 3 podstawowe rodzaje menu i prezentacji działań we wszystkich wersjach Androida:
- menu Opcje i pasek aplikacji.
- Menu opcji to podstawowy zbiór pozycji menu danej aktywności. Możesz tam dodawać działania, które mają globalny wpływ na działanie aplikacji, takie jak „Wyszukiwanie”, „Napisz e-maila” czy „Ustawienia”.
Zobacz sekcję Utwórz menu opcji.
- Menu kontekstowe i tryb działań kontekstowych
- Menu kontekstowe to pływające menu, które pojawia się, gdy użytkownik naciśnie i przytrzyma element. Zawiera ona działania, które wpływają na wybraną treść lub ramkę kontekstową.
Tryb działań kontekstowych wyświetla na pasku u góry ekranu działania, które mają wpływ na wybraną treść. Umożliwia on użytkownikowi wybranie kilku elementów.
Zobacz sekcję Tworzenie menu kontekstowego.
- Wyskakujące menu
- W menu znajduje się pionowa lista elementów zakotwiczonych w widoku, który wywołuje menu. Jest to przydatne, gdy udostępniasz dużo działań związanych z konkretną treścią lub udostępnia opcje dotyczące drugiej części polecenia. Działania w wyskakującym menu nie mają bezpośredniego wpływu na dane treści – od tego właśnie działają działania kontekstowe. Wyskakujące menu służy raczej do rozszerzonych działań związanych z regionami treści Twojej aktywności.
Zobacz sekcję Utwórz wyskakujące menu.
Definiowanie menu w pliku XML
W przypadku wszystkich typów menu Android udostępnia standardowy format XML do definiowania pozycji menu. Zamiast tworzyć menu w kodzie aktywności, zdefiniuj menu i wszystkie jego elementy w zasobie menu XML. Możesz następnie powiększyć zasób menu przez wczytanie go jako obiektu Menu
w aktywności lub fragmencie.
Korzystanie z zasobu menu jest zalecane z tych powodów:
- Ułatwia to wizualizację struktury menu w formacie XML.
- Oddziela zawartość menu od kodu behawioralnego aplikacji.
- Umożliwia tworzenie alternatywnych konfiguracji menu na potrzeby różnych wersji platformy, rozmiarów ekranu i innych konfiguracji za pomocą platformy 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 element
Menu
, który jest kontenerem na pozycje menu. Element<menu>
musi być węzłem głównym pliku i może zawierać co najmniej 1 element<item>
oraz<group>
. <item>
- Tworzy element
MenuItem
, który reprezentuje pojedynczy element menu. Ten element może zawierać zagnieżdżony element<menu>
tworzący menu podrzędne. <group>
- Opcjonalny, niewidoczny kontener na elementy
<item>
. Umożliwia kategoryzowanie elementów menu w taki sposób, aby miały wspólne właściwości, np. 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, za pomocą których można zdefiniować wygląd i zachowanie elementu. Elementy w poprzednim menu obejmują te atrybuty:
android:id
- Unikalny dla elementu identyfikator zasobu, dzięki któremu aplikacja może rozpoznać element, gdy użytkownik go wybierze.
android:icon
- Odniesienie do elementu, który można rysować i używania jako ikony elementu.
android:title
- Odwołanie do ciągu znaków, które służy jako tytuł elementu.
android:showAsAction
- Specyfikacja dotycząca tego, kiedy i w jaki sposób element wyświetla się jako działanie na pasku aplikacji.
To najważniejsze atrybuty, z których korzystasz, ale dostępnych jest też wiele innych. Informacje na temat wszystkich obsługiwanych atrybutów znajdziesz w dokumentacji zasobów menu.
Możesz dodać menu podrzędne do elementu w dowolnym menu, dodając element <menu>
jako element podrzędny <item>
.
Menu podrzędne są przydatne, gdy aplikacja zawiera wiele funkcji, które można uporządkować według tematów, takich jak pozycje na pasku menu aplikacji na PC, np. Plik, Edytuj i Widok. Przyjrzyj się temu przykładowi:
<?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_ konwertuj zasób XML na obiekt dostępny do programowania za pomocą MenuInflater.inflate()
.
W sekcjach poniżej dowiesz się, jak powiększać menu w przypadku poszczególnych typów menu.
Tworzenie menu opcji
W menu opcji, podobnie jak na ilustracji 1, możesz dodać działania i inne opcje związane z bieżącym kontekstem działań, np. „Wyszukiwanie”, „Napisz e-maila” i „Ustawienia”.
![Obraz przedstawiający pasek aplikacji Arkusze Google](https://developer.android.com/static/images/training/appbar/appbar_sheets_2x.png?authuser=7&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 użytkownika. Na początku wyświetlają się elementy działania, a po nim te z każdego fragmentu, w kolejności, w jakiej zostały one dodane do działania. W razie potrzeby możesz zmienić kolejność pozycji menu, korzystając z atrybutu android:orderInCategory
w każdym elemencie <item>
do przeniesienia.
Aby określić menu opcji danej aktywności, zastąp onCreateOptionsMenu()
.
Fragmenty zawierają własne wywołanie zwrotne onCreateOptionsMenu()
. Ta metoda pozwala uzupełnić zasób menu (zdefiniowany w pliku XML) do pliku Menu
podanego 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ą funkcji add()
i pobierać pozycje za pomocą funkcji findItem()
, aby modyfikować ich właściwości za pomocą interfejsów API MenuItem
.
Obsługa zdarzeń kliknięcia
Gdy użytkownik wybierze element w menu opcji, w tym działania na pasku aplikacji, system wywoła metodę onOptionsItemSelected()
Twojej aktywności. Ta metoda przekazuje wybrane dane (MenuItem
). Możesz zidentyfikować element, wywołując funkcję getItemId()
, która zwraca unikalny identyfikator pozycji menu zdefiniowany przez atrybut android:id
w zasobie menu lub liczbę całkowitą podaną w metodzie add()
. Możesz go dopasować do znanych pozycji menu,
by 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 obsługi pozycji menu, zwróć true
. Jeśli nie obsługujesz danego elementu menu, wywołaj implementację klasy nadrzędnej klasy onOptionsItemSelected()
. Domyślna implementacja zwraca wartość „false”.
Jeśli aktywność zawiera fragmenty, system najpierw wywołuje dla niej funkcję onOptionsItemSelected()
, a następnie dla każdego fragmentu w kolejności ich dodawania, aż do zwrócenia wartości true
lub wywołania wszystkich fragmentów.
Zmieniaj pozycje menu podczas działania
Po wywołaniu funkcji onCreateOptionsMenu()
system zachowuje instancję Menu
uzupełnioną przez Ciebie i nie wywołuje ponownie onCreateOptionsMenu()
, chyba że menu zostanie unieważnione.
Pamiętaj jednak, żeby używać onCreateOptionsMenu()
tylko do utworzenia początkowego stanu menu i nie wprowadzać zmian w trakcie cyklu życia aktywności.
Jeśli chcesz modyfikować menu opcji na podstawie zdarzeń występujących w trakcie cyklu życia aktywności, możesz to zrobić w metodzie onPrepareOptionsMenu()
. Ta metoda przekazuje obiekt Menu
w takiej postaci, w jakiej obecnie istnieje, dzięki czemu możesz go zmodyfikować, np. dodając, usuwając lub wyłączając elementy.
Fragmenty zawierają też wywołanie zwrotne onPrepareOptionsMenu()
.
Gdy elementy menu znajdują się na pasku aplikacji, menu opcji jest uważane za zawsze otwarte. Gdy wystąpi zdarzenie i chcesz zaktualizować menu, wywołaj invalidateOptionsMenu()
, aby zażądać wywołania systemowego onPrepareOptionsMenu()
.
Tworzenie menu kontekstowego
Menu kontekstowe zawiera działania, które wpływają na element lub ramkę kontekstową w interfejsie. Możesz podać menu kontekstowe dowolnego widoku, ale jest ono najczęściej używane w przypadku elementów w kolekcji RecylerView
lub innych widoków, w których użytkownik może bezpośrednio wykonywać działania związane z każdym elementem.
Działania kontekstowe można określić na 2 sposoby:
- w pływającym menu kontekstowym, Menu ma postać pływającej listy elementów menu, podobnie jak okno, gdy użytkownik naciśnie i przytrzyma 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 to implementacja systemowa
ActionMode
, która wyświetla u góry ekranu pasek działań kontekstowych(CAB) z działaniami wpływającymi na wybrane elementy. Gdy ten tryb jest aktywny, użytkownicy mogą wykonywać działania na wielu elementach jednocześnie, o ile Twoja aplikacja to umożliwia.
Tworzenie pływającego menu kontekstowego
Aby wyświetlić pływające menu kontekstowe:
- Zarejestruj element
View
, z którym jest powiązane menu kontekstowe, wywołując metodęregisterForContextMenu()
i przekazując jąView
.Jeśli Twoja aktywność korzysta z właściwości
RecyclerView
i chcesz, aby każdy element miał to samo menu kontekstowe, zarejestruj wszystkie elementy w menu kontekstowym, przekazującRecyclerView
doregisterForContextMenu()
. - Zaimplementuj metodę
onCreateContextMenu()
wActivity
lubFragment
.Gdy zarejestrowany widok otrzyma zdarzenie kliknięcia i przytrzymania, system wywoła metodę
onCreateContextMenu()
. W tym miejscu definiuje się elementy menu, zwykle dodając nadmiar 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 powiększyć menu kontekstowe z poziomu zasobu menu. Parametry metody wywołania zwrotnego obejmują obiektView
wybierany przez użytkownika oraz obiektContextMenu.ContextMenuInfo
, który zawiera dodatkowe informacje o wybranym elemencie. Jeśli Twoja aktywność ma kilka widoków danych, z których każdy zawiera inne menu kontekstowe, możesz na podstawie tych parametrów określić, które menu kontekstowe powiększyć. Wdróż
onContextItemSelected()
zgodnie z tym przykładem. Gdy użytkownik wybierze pozycję w menu, system wywołuje tę metodę, aby umożliwić Ci wykonanie odpowiedniego działania.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 do identyfikatora wybranej pozycji menu, która jest przypisywana do każdej pozycji menu w języku XML za pomocą atrybutuandroid:id
, jak pokazano w sekcji Definiowanie menu w języku XML.Gdy przejdziesz do obsługi pozycji menu, zwróć
true
. Jeśli nie obsługujesz elementu menu, przekaż je do implementacji klasy nadrzędnej. Jeśli aktywność zawiera fragmenty, najpierw otrzymuje to wywołanie zwrotne. Wywołując klasę nadrzędną, gdy jest nieobsługiwana, system przekazuje zdarzenie do odpowiedniej metody wywołania zwrotnego w każdym fragmencie – pojedynczo, w kolejności dodania każdego fragmentu, aż do zwrócenia wartościtrue
lubfalse
. Domyślne implementacjeActivity
iandroid.app.Fragment
zwracają wartościfalse
, więc zawsze wywołuj klasę nadrzędną, gdy jest nieobsługiwana.
Korzystanie z trybu działań kontekstowych
Tryb działań kontekstowych to implementacja systemowa elementu ActionMode
, która koncentruje się na interakcjach użytkownika z wykorzystaniem działań kontekstowych. Gdy użytkownik włączy ten tryb przez wybranie elementu, u góry ekranu wyświetli się pasek działań kontekstowych przedstawiający czynności, 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 obsługuje), odznaczyć elementy i kontynuować poruszanie się 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 wybierz działanie Gotowe po lewej stronie paska.
W przypadku widoków danych z działaniami kontekstowymi wywoływany jest tryb działań kontekstowych, gdy wystąpi co najmniej jedno z tych 2 zdarzeń:
- Użytkownik dotyka widoku i go przytrzymuje.
- Użytkownik zaznacza pole wyboru lub podobny komponent interfejsu w widoku.
Sposób, w jaki aplikacja wywołuje tryb działań kontekstowych i określa zachowanie w przypadku każdego działania, zależy od Twojego projektu. Dostępne są 2 projekty:
- Dla działań kontekstowych dotyczących poszczególnych, dowolnych widoków.
- Dotyczy zbiorczych działań kontekstowych na grupach elementów w elemencie
RecyclerView
, umożliwiając użytkownikowi wybranie wielu elementów i wykonanie na nich wszystkich działań.
W sekcjach poniżej opisujemy konfigurację wymaganą w każdym scenariuszu.
Włączanie trybu działań kontekstowych dla poszczególnych widoków danych
Jeśli chcesz wywoływać tryb działań kontekstowych tylko wtedy, gdy użytkownik wybierze określone widoki, wykonaj te czynności:
- Wdróż interfejs
ActionMode.Callback
zgodnie z tym przykładem. W metodach wywołań zwrotnych możesz określić działania na pasku działań kontekstowych, reagować na zdarzenia kliknięć elementów działań i obsługiwać inne zdarzenia cyklu życia w trybie 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 tym że każde z nich przekazuje również obiekt
ActionMode
powiązany ze zdarzeniem. Za pomocą interfejsów APIActionMode
możesz wprowadzać różne zmiany w CAB, np. poprawiać tytuł i podtytuł za pomocąsetTitle()
isetSubtitle()
, co przydaje się do wskazywania liczby wybranych elementów.Poprzedni przykład ustawia zmienną
actionMode
nanull
po zniszczeniu trybu działania. W następnym kroku sprawdź, jak jest zainicjowany i jak może pomóc zapisanie zmiennej członkowskiej w aktywności lub fragmencie. - Zadzwoń pod numer
startActionMode()
, jeśli chcesz wyświetlić pasek, np. gdy użytkownik kliknie i przytrzymaj 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
startActionMode()
, system zwróci utworzonyActionMode
. Zapisując ją w zmiennej członka, możesz wprowadzać zmiany na pasku działań kontekstowych w odpowiedzi na inne zdarzenia. W poprzednim przykładzie używana jest instancjaActionMode
, aby przed uruchomieniem trybu działania nie można było odtworzyć instancjiActionMode
, jeśli jest już aktywna.
Utwórz wyskakujące menu
![Obraz przedstawiający wyskakujące menu w aplikacji Gmail zakotwiczone obok przycisku menu w prawym górnym rogu.](https://developer.android.com/static/images/ui/popupmenu.png?authuser=7&hl=pl)
PopupMenu
to menu modalne powiązane z elementem View
. Pojawia się ona pod widokiem zakotwiczenia,
jeśli jest wystarczająco dużo miejsca, lub nad widokiem w innym przypadku. Jest to przydatne, gdy:
- Udostępnienie rozszerzonego menu działań odnoszących się do określonej treści, takich jak nagłówki e-maili w Gmailu, co widać na ilustracji 4.
- Podanie drugiej części zdania, na przykład przycisku oznaczonego Dodaj, który powoduje wyświetlenie menu z różnymi opcjami Dodaj.
- Udostępnianie menu podobnego do
Spinner
, które nie zachowuje stałego wyboru.
Jeśli zdefiniujesz menu w języku XML, menu możesz wyświetlić w ten sposób:
- Utwórz instancję
PopupMenu
za pomocą swojego konstruktora, który pobiera bieżącą aplikacjęContext
iView
, w których jest zakotwiczone menu. - Użyj
MenuInflater
, aby powiększyć zasób menu do obiektuMenu
zwracanego przezPopupMenu.getMenu()
. - Będziesz dzwonić pod numer
PopupMenu.show()
.
Oto przykład przycisku, który wyświetla wyskakujące 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" />
Aktywność może wtedy wyświetlić menu w ten sposób:
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. Nasłuchiwania zdarzenia odrzucenia możesz włączyć za pomocą polecenia 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 wybierze element, system wywoła w interfejsie wywołanie zwrotne onMenuItemClick()
.
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 o określonych cechach. Dzięki grupie możesz:
- Aby wyświetlić lub ukryć wszystkie elementy, użyj właściwości
setGroupVisible()
. - Włącz lub wyłącz wszystkie elementy używające właściwości
setGroupEnabled()
. - Określ, czy wszystkie elementy można sprawdzić za pomocą właściwości
setGroupCheckable()
.
Grupę możesz utworzyć, zagnieżdżając elementy <item>
wewnątrz elementu <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 tej grupie są wyświetlane na tym samym poziomie co pierwszy – wszystkie 3 elementy w menu są elementami równorzędnymi. Możesz jednak zmienić cechy 2 elementów w grupie, odwołując się do identyfikatora grupy i korzystając z poprzednich metod. Ponadto system nigdy nie rozdziela zgrupowanych elementów. Jeśli na przykład zadeklarujesz zasadę android:showAsAction="ifRoom"
dla każdego elementu, oba te elementy pojawią się na pasku działań lub oba będą widoczne w rozszerzonym menu działań.
Używaj elementów menu, które można zaznaczyć
Menu może służyć jako interfejs do włączania i wyłączania opcji, w tym z polem wyboru dla samodzielnych opcji lub przyciskami do grupowania wzajemnie się wykluczających opcji. Rys. 5 przedstawia menu podrzędne z elementami, które można zaznaczyć za pomocą przycisków opcji.
Możesz zdefiniować możliwość sprawdzania działania poszczególnych pozycji 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ć przyciskiem:
<?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 1 z tych wartości:
single
- Można zaznaczyć tylko jeden element z grupy, co spowoduje pojawienie się odpowiednich przycisków.
all
- Zaznaczyć można wszystkie elementy, co spowoduje pojawienie się pól wyboru.
none
- Brak elementów, które można zaznaczyć.
Możesz zastosować do elementu domyślny stan zaznaczonego pola za pomocą atrybutu android:checked
w elemencie <item>
i zmienić go w kodzie za pomocą metody setChecked()
.
Po wybraniu elementu, który można zaznaczyć, system wywołuje odpowiednią metodę wywołania zwrotnego wybranego elementu, np. onOptionsItemSelected()
.
W tym miejscu ustawia się stan pola wyboru, ponieważ pole wyboru lub opcja nie zmieniają stanu automatycznie. Możesz przesłać zapytanie dotyczące bieżącego stanu elementu (w takiej postaci, w jakiej był przed wybraniem go przez użytkownika) za pomocą funkcji isChecked()
, a następnie ustawić stan zaznaczonego elementu za pomocą funkcji setChecked()
. Widać to w tym przykładzie:
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 zaznaczenia w ten sposób, stan widoczności pola wyboru lub opcji nie zmieni się, gdy użytkownik go wybierze. Gdy określisz stan, aktywność zachowa zaznaczony stan elementu – gdy użytkownik później otworzy menu, stan, który został przez Ciebie zaznaczony, będzie widoczny.
Dodawanie pozycji menu na podstawie intencji
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 w innej aplikacji. Jeśli znasz intencję, której chcesz użyć, i masz określoną pozycję w menu, która inicjuje intencję, możesz wykonać intencję za pomocą polecenia startActivity()
za pomocą odpowiedniej metody wywołania zwrotnego wybranego elementu, np. wywołania zwrotnego onOptionsItemSelected()
.
Jeśli jednak nie masz pewności, że urządzenie użytkownika zawiera aplikację, która obsługuje intencję, dodanie wywołującego ją elementu menu 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 wykryje na urządzeniu działania, które obsługują daną intencję.
Aby dodać pozycje menu na podstawie dostępnych działań, które akceptują intencję, wykonaj te czynności:
- Zdefiniuj intencję, używając kategorii
CATEGORY_ALTERNATIVE
lubCATEGORY_SELECTED_ALTERNATIVE
albo obu tych opcji i uwzględniając inne wymagania. - Zadzwoń pod numer
Menu.addIntentOptions()
. Android wyszuka wszystkie aplikacje, które mogą wykonać intencję, i dodaje je do Twojego menu.
Jeśli nie masz zainstalowanych aplikacji, które spełniają wymagania tego zamiaru, pozycje 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; }
Do każdego znalezionego działania, który dostarcza filtr intencji pasujący do zdefiniowanej intencji, dodawana jest pozycja menu z wartością w polu android:label
filtra intencji jako tytułem menu, a ikoną aplikacji – z ikoną elementu menu. Metoda addIntentOptions()
zwraca liczbę dodanych elementów menu.
Zezwalaj na dodawanie aktywności do innych menu
Możesz oferować usługi związane z Twoją aktywnością innym aplikacjom, aby można było dodać Twoją aplikację do menu innych użytkowników, odwracając role opisane wcześniej.
Aby znaleźć się w innych menu aplikacji, zdefiniuj filtr intencji w zwykły sposób, ale uwzględnij w nim wartość CATEGORY_ALTERNATIVE
lub CATEGORY_SELECTED_ALTERNATIVE
(albo obie te wartości) w przypadku kategorii filtra intencji. 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 pisaniu filtrów intencji znajdziesz w artykule o filtrach intencji i intencji.