Menu to popularny element interfejsu użytkownika w wielu typach aplikacji. Aby zapewnić użytkownikom spójne i znajome środowisko, używaj interfejsów Menu API do wyświetlania działań użytkownika i innych opcji w swoich aktywnościach.
W tym dokumencie pokazujemy, jak utworzyć 3 podstawowe typy menu lub prezentacji działań na wszystkich wersjach Androida:
- Menu opcji i pasek aplikacji
- Menu opcji to główny zbiór elementów menu aktywności. Umieszcza się w nim działania, które mają globalny wpływ na aplikację, np. „Wyszukaj”, „Utwórz e-maila” i „Ustawienia”.
Zapoznaj się z 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 przytrzyma element. Umożliwia wykonywanie działań, które wpływają na wybraną treść lub ramkę kontekstu.
Tryb działania kontekstowego wyświetla elementy działania, które wpływają na wybrane treści na pasku u góry ekranu, i umożliwia użytkownikowi wybór wielu elementów.
Zapoznaj się z sekcją Tworzenie menu kontekstowego.
- Wyskakujące menu
- Menu wyskakujące wyświetla pionową listę elementów, która jest zakotwiczona w widoku wywołującym menu. Jest to przydatne w przypadku dodatkowych działań związanych z określonymi treściami lub opcji drugiej części polecenia. Działania w menu wyskakującym nie wpływają bezpośrednio na odpowiednie treści – do tego służą działania kontekstowe. Menu wyskakujące służy do wykonywania rozszerzonych działań związanych z obszarami treści w Twojej aktywności.
Zapoznaj się z sekcją Tworzenie menu wyskakującego.
Definiowanie menu w 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 zasobie menu w formacie XML. Następnie możesz rozwinąć zasób menu – wczytać go jako obiekt Menu
w aktywności lub fragmencie.
Używanie zasobu menu jest dobrym rozwiązaniem z tych powodów:
- Łatwiej jest wizualizować strukturę menu w XML.
- Oddziela zawartość menu od kodu behawioralnego aplikacji.
- Umożliwia tworzenie alternatywnych konfiguracji menu dla różnych wersji platformy, rozmiarów ekranu i innych konfiguracji dzięki wykorzystaniu struktury zasobów aplikacji.
Aby zdefiniować menu, utwórz plik XML w katalogu res/menu/ projektu i skonstruuj menu za pomocą tych elementów:
<menu>- Definiuje
Menu, czyli kontener 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, który reprezentuje pojedynczy element w menu. Ten element może zawierać zagnieżdżony element<menu>, aby utworzyć podmenu. <group>- Opcjonalny, niewidoczny kontener dla elementów
<item>. Umożliwia kategoryzowanie elementów menu, aby miały wspólne właściwości, takie jak stan aktywny 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żesz użyć do określenia wyglądu i działania elementu. Elementy w menu powyżej zawierają te atrybuty:
android:id- Identyfikator zasobu, który jest unikalny dla danego elementu i umożliwia aplikacji rozpoznanie go, gdy użytkownik go wybierze.
android:icon- Odwołanie do obiektu rysowalnego, który ma być używany jako ikona elementu.
android:title- Odwołanie do ciągu znaków, który ma być używany jako tytuł produktu.
android:showAsAction- Specyfikacja określająca, kiedy i jak ten element ma się pojawiać 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 zasobu Menu.
Podmenu możesz dodać do elementu w dowolnym menu, dodając element
<menu> jako element podrzędny elementu <item>.
Podmenu są przydatne, gdy aplikacja ma wiele funkcji, które można podzielić na tematy, np. elementy paska menu aplikacji na komputerze, takie jak Plik, Edycja 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, _rozwiń_ zasób menu, przekształcając zasób XML w obiekt programowalny za pomocą MenuInflater.inflate().
W sekcjach poniżej znajdziesz informacje o tym, jak rozwinąć menu każdego typu.
Tworzenie menu opcji
Menu opcji, takie jak to pokazane na ilustracji 1, zawiera działania i inne opcje związane z bieżącym kontekstem aktywności, takie jak „Szukaj”, „Utwórz e-maila” i „Ustawienia”.
Elementy menu opcji możesz zadeklarować w klasie podrzędnej Activitylub w klasie podrzędnej Fragment. Jeśli zarówno aktywność, jak i fragmenty deklarują elementy menu opcji, są one łączone w interfejsie. Najpierw pojawiają się elementy aktywności, a potem elementy poszczególnych fragmentów w kolejności, w jakiej fragmenty są dodawane do aktywności. W razie potrzeby możesz zmienić kolejność elementów menu za pomocą atrybutu android:orderInCategory w każdym <item>, który chcesz przenieść.
Aby określić menu opcji dla aktywności, zastąp wartość
onCreateOptionsMenu().
Fragmenty mają własne wywołanie zwrotne onCreateOptionsMenu(). W tej metodzie możesz rozwinąć zasób menu zdefiniowany w XML do obiektu Menu podanego w wywołaniu zwrotnym. Pokazuje to poniższy 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ć pozycje menu za pomocą elementu
add()
i pobierać je za pomocą elementu
findItem()
, aby zmieniać 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ła metodę onOptionsItemSelected()
aktywności. Ta metoda przekazuje wybraną wartość 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(). Możesz dopasować ten identyfikator 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); } }
Jeśli obsłużysz element menu, zwróć wartość true. Jeśli nie obsługujesz elementu menu, wywołaj implementację klasy nadrzędnej onOptionsItemSelected(). Domyślna implementacja zwraca wartość false.
Jeśli aktywność zawiera fragmenty, system najpierw wywołuje metodę onOptionsItemSelected() dla aktywności, a potem dla każdego fragmentu w kolejności dodawania fragmentów, dopóki jeden z nich nie zwróci wartości true lub dopóki nie zostaną wywołane wszystkie fragmenty.
Zmienianie pozycji menu w czasie działania
Po wywołaniu funkcji onCreateOptionsMenu() system zachowuje instancję funkcji Menu, którą wypełniasz, i nie wywołuje ponownie funkcji onCreateOptionsMenu(), chyba że menu zostanie unieważnione.
Używaj jednak onCreateOptionsMenu() 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ń, które występują w trakcie cyklu życia działania, możesz to zrobić w metodzie onPrepareOptionsMenu(). Ta metoda przekazuje obiekt Menu w jego obecnej postaci, dzięki czemu możesz go modyfikować, np. dodawać, usuwać lub wyłączać elementy.
Fragmenty udostępniają też wywołanie zwrotne onPrepareOptionsMenu().
Menu opcji jest zawsze otwarte, gdy elementy menu są wyświetlane na pasku aplikacji. Gdy wystąpi zdarzenie i chcesz zaktualizować menu, wywołaj invalidateOptionsMenu(), aby poprosić system o wywołanie onPrepareOptionsMenu().
Tworzenie menu kontekstowego
Menu kontekstowe zawiera działania, które wpływają na konkretny element lub ramkę kontekstową w interfejsie. Menu kontekstowe możesz udostępnić w dowolnym widoku, ale najczęściej jest ono używane w przypadku elementów w RecylerView lub innych kolekcjach widoków, w których użytkownik może wykonywać bezpośrednie działania na poszczególnych elementach.
Dostępne są 2 sposoby udostępniania działań kontekstowych:
- W pływającym menu kontekstowym. Menu pojawia się jako pływająca lista elementów menu, podobnie jak okno, gdy użytkownik dotknie i przytrzyma widok, który obsługuje menu kontekstowe. Użytkownicy mogą wykonywać czynności kontekstowe na jednym elemencie naraz.
- w trybie czynności kontekstowej. Ten tryb jest implementacją systemową
ActionMode, która wyświetla kontekstowy pasek działań u góry ekranu z elementami działań wpływającymi na wybrane elementy. Gdy ten tryb jest aktywny, użytkownicy mogą wykonywać działania na wielu elementach jednocześnie, jeśli Twoja aplikacja to obsługuje.
Uwaga: menu kontekstowe nie obsługuje skrótów ani ikon elementów.
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 funkcjęregisterForContextMenu()i przekazując jej elementView.Jeśli Twoja aktywność korzysta z
RecyclerViewi chcesz, aby każdy element udostępniał to samo menu kontekstowe, zarejestruj wszystkie elementy w menu kontekstowym, przekazującRecyclerViewdoregisterForContextMenu(). - Zaimplementuj metodę
onCreateContextMenu()wActivitylubFragment.Gdy zarejestrowany widok otrzyma zdarzenie dotknięcia i przytrzymania, system wywoła metodę
onCreateContextMenu(). W tym miejscu definiujesz pozycje menu, zwykle przez rozszerzenie 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); }
MenuInflaterumożliwia rozwijanie menu kontekstowego z zasobu menu. Parametry metody wywołania zwrotnego obejmują obiektViewwybrany przez użytkownika oraz obiektContextMenu.ContextMenuInfo, który zawiera dodatkowe informacje o wybranym produkcie. Jeśli Twoja aktywność ma kilka widoków, z których każdy udostępnia inne menu kontekstowe, możesz użyć tych parametrów, aby określić, które menu kontekstowe ma zostać rozwinięte. Zaimplementuj
onContextItemSelected(), jak pokazano w tym przykładzie. Gdy użytkownik wybierze element menu, system wywoła 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()wykonuje zapytanie o identyfikator wybranego elementu menu, który przypisujesz do każdego elementu menu w XML za pomocą atrybutuandroid:id, jak pokazano w sekcji Definiowanie menu w XML.Jeśli obsłużysz element menu, zwróć wartość
true. Jeśli nie obsługujesz elementu menu, przekaż go do implementacji klasy nadrzędnej. Jeśli aktywność zawiera fragmenty, najpierw otrzymuje to wywołanie zwrotne. Wywołując klasę nadrzędną w przypadku nieobsłużonego zdarzenia, system przekazuje zdarzenie do odpowiedniej metody wywołania zwrotnego w każdym fragmencie, po jednym na raz, w kolejności dodawania fragmentów, dopóki nie zostanie zwrócona wartośćtruelubfalse. Domyślne implementacje funkcjiActivityiandroid.app.Fragmentzwracająfalse, więc w przypadku nieobsłużonych zdarzeń zawsze wywołuj klasę nadrzędną.
Korzystanie z trybu czynności kontekstowej
Tryb czynności kontekstowej to implementacja systemowa ActionMode, która koncentruje interakcję użytkownika na wykonywaniu czynności kontekstowych. Gdy użytkownik włączy ten tryb, wybierając element, u góry ekranu pojawi się kontekstowy pasek działań, na którym będą widoczne działania, jakie użytkownik 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) i odznaczyć elementy oraz kontynuować nawigację w aktywności. Tryb działania jest wyłączony, a pasek czynności kontekstowych znika, gdy użytkownik odznaczy wszystkie elementy, kliknie przycisk Wstecz lub kliknie działanie Gotowe po lewej stronie paska.
W przypadku widoków, które udostępniają działania kontekstowe, tryb czynności kontekstowej jest zwykle wywoływany, gdy wystąpi co najmniej 1 z tych 2 zdarzeń:
- Użytkownik naciska i przytrzymuje widok.
- Użytkownik zaznacza pole wyboru lub podobny komponent interfejsu w widoku.
Sposób wywoływania trybu działania kontekstowego przez aplikację i definiowania zachowania dla każdego działania zależy od projektu. Dostępne są 2 wzory:
- W przypadku działań kontekstowych w odniesieniu do poszczególnych, dowolnych widoków.
- W przypadku działań kontekstowych wykonywanych zbiorczo na grupach elementów w
RecyclerView, umożliwiających użytkownikowi wybieranie wielu elementów i wykonywanie na nich wszystkich działania.
W sekcjach poniżej opisujemy konfigurację wymaganą w pierwszym scenariuszu.
Włączanie trybu czynności kontekstowej w przypadku poszczególnych widoków
Jeśli chcesz wywoływać tryb czynności kontekstowej tylko wtedy, gdy użytkownik wybierze określone widoki, wykonaj te czynności:
- Zaimplementuj interfejs
ActionMode.Callbackw sposób pokazany w tym przykładzie. W metodach wywołania zwrotnego możesz określić działania dla paska czynności kontekstowych, reagować na zdarzenia kliknięcia elementów działań i obsługiwać inne zdarzenia cyklu życia 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ą niemal identyczne z wywołaniami zwrotnymi menu opcji, z tym wyjątkiem, że każde z nich przekazuje też obiekt
ActionModepowiązany ze zdarzeniem. Za pomocą interfejsów APIActionModemożesz wprowadzać różne zmiany w CAB, np. zmieniać tytuł i podtytuł za pomocą funkcjisetTitle()isetSubtitle(), co jest przydatne, aby wskazać, ile elementów jest zaznaczonych.W powyższym przykładzie zmienna
actionModejest ustawiana nanull, gdy tryb działania jest niszczony. W następnym kroku dowiesz się, jak go zainicjować i jak może się przydać zapisanie zmiennej w aktywności lub fragmencie. - Wywołaj
startActionMode()gdy chcesz wyświetlić pasek, np. gdy użytkownik dotknie widoku i przytrzyma go.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 zwróci utworzony elementActionMode. Zapisując ten element w zmiennej składowej, możesz wprowadzać zmiany w pasku czynności kontekstowych w odpowiedzi na inne zdarzenia. W powyższym przykładzieActionModesłuży do zapewnienia, że instancjaActionModenie zostanie ponownie utworzona, jeśli jest już aktywna. W tym celu przed rozpoczęciem trybu działania sprawdzane jest, czy element członkowski ma wartość null.
Tworzenie menu wyskakującego
PopupMenu to menu modalne zakotwiczone w View. Pojawi się pod widokiem kotwicy, jeśli jest na to miejsce, lub nad nim. Jest przydatna w przypadku:
- Udostępnianie menu w stylu przepełnienia dla działań, które są powiązane z określonymi treściami, np. nagłówkami e-maili w Gmailu, jak pokazano na ilustracji 4.
- Podanie drugiej części zdania polecenia, np. przycisku oznaczonego jako Dodaj, który wyświetla menu z różnymi opcjami Dodaj.
- Wyświetlanie menu podobnego do
Spinner, które nie zachowuje trwałego wyboru.
Jeśli definiujesz menu w XML, możesz wyświetlić menu wyskakujące w ten sposób:
- Utwórz instancję klasy
PopupMenuza pomocą konstruktora, który przyjmuje bieżącą aplikacjęContexti elementView, do którego jest przypięte menu. - Użyj
MenuInflater, aby rozwinąć zasób menu w obiektMenuzwrócony przezPopupMenu.getMenu(). - Zadzwoń:
PopupMenu.show()
Oto przykładowy przycisk, który wyświetla menu wyskakujące:
<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 aktywności może się wtedy wyświetlić menu wyskakujące, jak poniżej:
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 element lub kliknie poza obszarem menu. Możesz nasłuchiwać zdarzenia zamknięcia za pomocą kodu
PopupMenu.OnDismissListener.
Obsługa zdarzeń kliknięcia
Aby wykonać działanie, gdy użytkownik wybierze element menu, zaimplementuj interfejs PopupMenu.OnMenuItemClickListener i zarejestruj go w PopupMenu, wywołując setOnMenuItemclickListener().
Gdy użytkownik wybierze element, system wywoła funkcję zwrotną onMenuItemClick() w interfejsie.
Pokazuje to poniższy 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, które mają pewne wspólne cechy. W grupie możesz:
- Wyświetl lub ukryj wszystkie elementy za pomocą ikony
setGroupVisible(). - Włącz lub wyłącz wszystkie produkty za pomocą
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 określając identyfikator grupy za pomocą metody add().
Oto przykład zasobu menu, który zawiera 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 równorzędnymi. Możesz jednak modyfikować cechy 2 produktów w grupie, odwołując się do identyfikatora grupy i korzystając z opisanych wcześniej metod. System nigdy nie rozdziela też zgrupowanych elementów. Jeśli na przykład zadeklarujesz android:showAsAction="ifRoom" dla każdego elementu, oba pojawią się na pasku działań lub w menu działań.
Korzystanie z pozycji menu z możliwością zaznaczenia
Menu może być przydatnym interfejsem do włączania i wyłączania opcji. W przypadku pojedynczych opcji można używać pól wyboru, a w przypadku grup wzajemnie wykluczających się opcji – przycisków opcji. Ilustracja 5 przedstawia menu podrzędne z elementami, które można zaznaczyć za pomocą przycisków opcji.
Zachowanie elementu menu, które można zaznaczyć, możesz zdefiniować 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- Można zaznaczyć tylko 1 element z grupy, co spowoduje wyświetlenie przycisków opcji.
all- Wszystkie elementy można zaznaczyć, co spowoduje wyświetlenie pól wyboru.
none- Nie można zaznaczyć żadnych elementów.
Możesz zastosować domyślny stan zaznaczenia elementu za pomocą atrybutu android:checked w elemencie <item> i zmienić go w kodzie za pomocą metody setChecked().
Gdy użytkownik wybierze element, który można zaznaczyć, system wywoła odpowiednią metodę wywołania zwrotnego wybranego elementu, np. onOptionsItemSelected().
W tym miejscu ustawiasz stan pola wyboru, ponieważ pole wyboru lub przycisk opcji nie zmieniają stanu automatycznie. Możesz wysłać zapytanie o bieżący stan elementu – taki, jaki był przed wybraniem go przez użytkownika – za pomocą isChecked(), a następnie ustawić stan zaznaczenia za pomocą setChecked(). Pokazuje to poniższy 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 zaznaczenia w ten sposób, widoczny stan pola wyboru lub przycisku opcji nie zmieni się, gdy użytkownik go wybierze. Gdy ustawisz stan, aktywność zachowa stan zaznaczenia elementu, dzięki czemu, gdy użytkownik otworzy menu później, będzie widoczny ustawiony przez Ciebie stan zaznaczenia.
Dodawanie pozycji menu na podstawie intencji
Czasami chcesz, aby element menu uruchamiał działanie za pomocą 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 konkretny element menu, który ją inicjuje, możesz wykonać intencję za pomocą startActivity() w odpowiedniej metodzie wywołania zwrotnego on-item-selected, takiej jak wywołanie zwrotne onOptionsItemSelected().
Jeśli jednak nie masz pewności, czy na urządzeniu użytkownika znajduje się aplikacja, która obsługuje intencję, dodanie elementu menu, który ją wywołuje, może spowodować, że element menu nie będzie działać, ponieważ intencja może nie zostać przekształcona w aktywność. Aby rozwiązać ten problem, Android umożliwia dynamiczne dodawanie elementów menu do menu, gdy znajdzie na urządzeniu aktywności, które obsługują Twoją intencję.
Aby dodać elementy menu na podstawie dostępnych działań, które akceptują intencję, wykonaj te czynności:
- Określ intencję za pomocą kategorii
CATEGORY_ALTERNATIVElubCATEGORY_SELECTED_ALTERNATIVEalbo obu tych kategorii, a także innych wymagań. - Zadzwoń pod numer
Menu.addIntentOptions(). Android wyszukuje aplikacje, które mogą wykonać intencję, i dodaje je do menu.
Jeśli nie ma zainstalowanych aplikacji, które spełniają intencję, nie są dodawane żadne elementy menu.
Pokazuje to poniższy 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; }
Dla każdej znalezionej aktywności, która zapewnia filtr intencji pasujący do zdefiniowanej intencji, dodawany jest element menu. Jako tytuł elementu menu używana jest wartość z android:label filtra intencji, a jako ikona elementu menu – ikona aplikacji. Metoda addIntentOptions() zwraca liczbę dodanych elementów menu.
Zezwalaj na dodawanie Twojej aktywności do innych menu
Możesz udostępniać usługi swojej aktywności innym aplikacjom, aby Twoja aplikacja mogła być uwzględniana w menu innych aplikacji – odwracając role opisane wcześniej.
Aby aplikacja była widoczna w menu innych aplikacji, zdefiniuj filtr intencji w zwykły sposób, ale w przypadku kategorii filtra intencji uwzględnij wartości CATEGORY_ALTERNATIVE lub CATEGORY_SELECTED_ALTERNATIVE albo obie te wartości. Pokazuje to poniższy 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 pisaniu filtrów intencji znajdziesz w artykule Intencje i filtry intencji.