Aggiungi menu

Prova Compose
Jetpack Compose è il toolkit per la UI consigliato per Android. Scopri come aggiungere componenti in Compose.

I menu sono un componente comune dell'interfaccia utente in molti tipi di app. Per offrire un'esperienza utente familiare e coerente, utilizza le API Menu per presentare le azioni dell'utente e altre opzioni nelle tue attività.

Un'immagine che mostra un esempio di menu overflow
Figura 1. Un menu attivato da un tocco dell'icona, che appare sotto l'icona del menu extra.

Questo documento mostra come creare i tre tipi fondamentali di menu o presentazioni di azioni su tutte le versioni di Android:

Menu Opzioni e barra delle app
Il menu opzioni è la raccolta principale di voci di menu per un'Activity. È qui che inserisci le azioni che hanno un impatto globale sull'app, come "Cerca", "Scrivi email" e "Impostazioni".

Consulta la sezione Creare un menu opzioni.

Menu contestuale e modalità azione contestuale
Un menu contestuale è un menu mobile che viene visualizzato quando l'utente tocca e tiene premuto un elemento. Fornisce azioni che influiscono sui contenuti selezionati o sul frame di contesto.

La modalità di azione contestuale mostra gli elementi di azione che influenzano i contenuti selezionati in una barra nella parte superiore dello schermo e consente all'utente di selezionare più elementi.

Consulta la sezione Creare un menu contestuale.

Menu popup
Un menu popup mostra un elenco verticale di elementi ancorato alla visualizzazione che richiama il menu. È utile per fornire un overflow di azioni correlate a contenuti specifici o per fornire opzioni per la seconda parte di un comando. Le azioni in un menu popup non influiscono direttamente sui contenuti corrispondenti, a questo servono le azioni contestuali. Il menu popup è invece destinato alle azioni estese relative alle regioni di contenuti nella tua attività.

Consulta la sezione Creare un menu popup.

Definire un menu in XML

Per tutti i tipi di menu, Android fornisce un formato XML standard per definire le voci di menu. Anziché creare un menu nel codice dell'attività, definisci un menu e tutti i relativi elementi in una risorsa di menu XML. Puoi poi gonfiare la risorsa del menu, caricandola come oggetto Menu nell'attività o nel fragment.

L'utilizzo di una risorsa di menu è una buona pratica per i seguenti motivi:

  • È più facile visualizzare la struttura del menu in XML.
  • Separa i contenuti del menu dal codice comportamentale dell'app.
  • Consente di creare configurazioni di menu alternative per diverse versioni della piattaforma, dimensioni dello schermo e altre configurazioni sfruttando il framework delle risorse dell'app.

Per definire un menu, crea un file XML all'interno della directory res/menu/ del progetto e crea il menu con i seguenti elementi:

<menu>
Definisce un Menu, ovvero un contenitore per le voci di menu. Un elemento <menu> deve essere il nodo radice del file e può contenere uno o più elementi <item> e <group>.
<item>
Crea un MenuItem, che rappresenta un singolo elemento in un menu. Questo elemento può contenere un elemento <menu> nidificato per creare un sottomenu.
<group>
Un contenitore invisibile facoltativo per gli elementi <item>. Consente di classificare le voci di menu in modo che condividano proprietà, ad esempio stato attivo e visibilità. Per saperne di più, consulta la sezione Creare un gruppo di menu.

Ecco un menu di esempio denominato 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>

L'elemento <item> supporta diversi attributi che puoi utilizzare per definire l'aspetto e il comportamento di un elemento. Gli elementi del menu precedente includono i seguenti attributi:

android:id
Un ID risorsa univoco per l'elemento, che consente all'app di riconoscerlo quando l'utente lo seleziona.
android:icon
Un riferimento a una risorsa disegnabile da utilizzare come icona dell'elemento.
android:title
Un riferimento a una stringa da utilizzare come titolo dell'elemento.
android:showAsAction
La specifica di quando e come questo elemento viene visualizzato come attività nella barra dell'app.

Questi sono gli attributi più importanti che utilizzi, ma ne sono disponibili molti altri. Per informazioni su tutti gli attributi supportati, consulta la documentazione Risorsa menu.

Puoi aggiungere un sottomenu a un elemento di qualsiasi menu aggiungendo un elemento <menu> come elemento secondario di un <item>. I sottomenu sono utili quando l'app ha molte funzioni che possono essere organizzate in argomenti, come gli elementi della barra dei menu di un'app per PC, ad esempio File, Modifica e Visualizza. Vedi l'esempio di seguito:

<?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>

Per utilizzare il menu nella tua attività, _gonfia_ la risorsa del menu, convertendo la risorsa XML in un oggetto programmabile utilizzando MenuInflater.inflate(). Le sezioni seguenti mostrano come gonfiare un menu per ogni tipo di menu.

Creare un menu opzioni

Il menu delle opzioni, come quello mostrato nella figura 1, è il punto in cui includere azioni e altre opzioni pertinenti al contesto dell'attività corrente, come "Cerca", "Scrivi email" e "Impostazioni".

Un&#39;immagine che mostra la barra delle app per l&#39;app Fogli Google
Figura 2. L'app Fogli Google, che mostra diversi pulsanti, incluso il pulsante del menu extra.

Puoi dichiarare elementi per il menu opzioni dalla tua sottoclasse Activity o da una sottoclasse Fragment. Se sia l'attività che i frammenti dichiarano elementi per il menu delle opzioni, gli elementi vengono combinati nell'interfaccia utente. Gli elementi dell'attività vengono visualizzati per primi, seguiti da quelli di ogni frammento, nell'ordine in cui i frammenti vengono aggiunti all'attività. Se necessario, puoi riordinare le voci di menu con l'attributo android:orderInCategory in ogni <item> che devi spostare.

Per specificare il menu opzioni per un'attività, esegui l'override di onCreateOptionsMenu(). I fragment forniscono il proprio callback onCreateOptionsMenu(). Con questo metodo, puoi gonfiare la risorsa del menu, definita in XML, nel Menu fornito nel callback. Ciò è mostrato nel seguente esempio:

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;
}

Puoi anche aggiungere voci di menu utilizzando add() e recuperare elementi con findItem() per rivedere le loro proprietà con le API MenuItem.

Gestire gli eventi di clic

Quando l'utente seleziona un elemento dal menu delle opzioni, inclusi gli elementi di azione nella barra delle app, il sistema chiama il metodo onOptionsItemSelected() dell'attività. Questo metodo passa il MenuItem selezionato. Puoi identificare l'elemento chiamando getItemId(), che restituisce l'ID univoco della voce di menu, definito dall'attributo android:id nella risorsa menu o con un numero intero fornito al metodo add(). Puoi confrontare questo ID con le voci di menu note per eseguire l'azione appropriata.

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);
    }
}

Quando gestisci correttamente una voce di menu, restituisci true. Se non gestisci la voce di menu, chiama l'implementazione della superclasse di onOptionsItemSelected(). L'implementazione predefinita restituisce false.

Se l'attività include frammenti, il sistema chiama prima onOptionsItemSelected() per l'attività, poi per ogni frammento nell'ordine in cui vengono aggiunti, finché uno non restituisce true o vengono chiamati tutti i frammenti.

Modificare le voci di menu in fase di runtime

Dopo che il sistema chiama onCreateOptionsMenu(), conserva un'istanza di Menu che compili e non chiama di nuovo onCreateOptionsMenu() a meno che il menu non venga invalidato. Tuttavia, utilizza onCreateOptionsMenu() solo per creare lo stato iniziale del menu e non per apportare modifiche durante il ciclo di vita dell'attività.

Se vuoi modificare il menu opzioni in base agli eventi che si verificano durante il ciclo di vita dell'attività, puoi farlo nel metodo onPrepareOptionsMenu(). Questo metodo ti trasmette l'oggetto Menu così com'è attualmente in modo che tu possa modificarlo, ad esempio aggiungendo, rimuovendo o disattivando elementi. I fragment forniscono anche un onPrepareOptionsMenu() callback.

Il menu opzioni è considerato sempre aperto quando le voci di menu vengono presentate nella barra delle app. Quando si verifica un evento e vuoi eseguire un aggiornamento del menu, chiama invalidateOptionsMenu() per richiedere al sistema di chiamare onPrepareOptionsMenu().

Creare un menu contestuale

Un&#39;immagine che mostra un menu contestuale mobile
Figura 3. Un menu contestuale mobile.

Un menu contestuale offre azioni che influiscono su un elemento o un frame di contesto specifico nell'interfaccia utente. Puoi fornire un menu contestuale per qualsiasi visualizzazione, ma vengono utilizzati più spesso per gli elementi di una RecylerView o di altre raccolte di visualizzazioni in cui l'utente può eseguire azioni dirette su ogni elemento.

Esistono due modi per fornire azioni contestuali:

  • In un menu contestuale mobile. Un menu viene visualizzato come un elenco mobile di voci di menu, simile a una finestra di dialogo, quando l'utente esegue un tocco e tieni premuto su una visualizzazione che dichiara il supporto di un menu contestuale. Gli utenti possono eseguire un'azione contestuale su un elemento alla volta.
  • Nella modalità azione contestuale. Questa modalità è un'implementazione di sistema di ActionMode che mostra una barra delle azioni contestuale, o CAB, nella parte superiore dello schermo con elementi di azione che influiscono sugli elementi selezionati. Quando questa modalità è attiva, gli utenti possono eseguire un'azione su più elementi contemporaneamente, se la tua app lo supporta.

Nota:il menu contestuale non supporta le scorciatoie e le icone degli elementi.

Creare un menu contestuale mobile

Per fornire un menu contestuale mobile:

  1. Registra il View a cui è associato il menu contestuale chiamando registerForContextMenu() e passando il View.

    Se la tua attività utilizza un RecyclerView e vuoi che ogni elemento fornisca lo stesso menu contestuale, registra tutti gli elementi per un menu contestuale passando RecyclerView a registerForContextMenu().

  2. Implementa il metodo onCreateContextMenu() in Activity o Fragment.

    Quando la visualizzazione registrata riceve un evento tocco e tieni premuto, il sistema chiama il metodo onCreateContextMenu(). Qui definisci le voci di menu, in genere gonfiando una risorsa di menu, come nel seguente esempio:

    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 consente di gonfiare il menu contestuale da una risorsa di menu. I parametri del metodo di callback includono View selezionato dall'utente e un oggetto ContextMenu.ContextMenuInfo che fornisce informazioni aggiuntive sull'elemento selezionato. Se la tua attività ha diverse visualizzazioni, ognuna delle quali fornisce un menu contestuale diverso, potresti utilizzare questi parametri per determinare quale menu contestuale visualizzare.

  3. Implementa onContextItemSelected(), come mostrato nell'esempio seguente. Quando l'utente seleziona una voce di menu, il sistema chiama questo metodo per consentirti di eseguire l'azione appropriata.

    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);
            }
        }
        

    Il metodo getItemId() esegue una query sull'ID della voce di menu selezionata, che assegni a ogni voce di menu in XML utilizzando l'attributo android:id, come mostrato in Definire un menu in XML.

    Quando gestisci correttamente una voce di menu, restituisci true. Se non gestisci la voce di menu, passala all'implementazione della superclasse. Se la tua attività include frammenti, riceve prima questo callback. Se la superclasse viene chiamata quando non viene gestito, il sistema passa l'evento al rispettivo metodo di callback in ogni frammento, uno alla volta, nell'ordine in cui viene aggiunto ogni frammento, finché non viene restituito true o false. Le implementazioni predefinite per Activity e android.app.Fragment restituiscono false, quindi chiama sempre la superclasse quando non gestita.

Utilizzare la modalità azione contestuale

La modalità Azione contestuale è un'implementazione di sistema di ActionMode che concentra l'interazione dell'utente sull'esecuzione di azioni contestuali. Quando un utente attiva questa modalità selezionando un elemento, nella parte superiore dello schermo viene visualizzata una barra delle azioni contestuali che mostra le azioni che l'utente può eseguire sugli elementi selezionati. Quando questa modalità è attiva, l'utente può selezionare più elementi, se la tua app lo supporta, e può deselezionare gli elementi e continuare a navigare all'interno dell'attività. La modalità di azione è disattivata e la barra delle azioni contestuali scompare quando l'utente deseleziona tutti gli elementi, tocca il pulsante Indietro o tocca l'azione Fine sul lato sinistro della barra.

Per le visualizzazioni che forniscono azioni contestuali, in genere si richiama la modalità azione contestuale quando si verifica uno o entrambi questi eventi:

  • L'utente tocca e tiene premuta la visualizzazione.
  • L'utente seleziona una casella di controllo o un componente UI simile all'interno della visualizzazione.

Il modo in cui la tua app richiama la modalità azione contestuale e definisce il comportamento per ogni azione dipende dal tuo design. Esistono due design:

  • Per le azioni contestuali su visualizzazioni individuali e arbitrarie.
  • Per azioni contestuali batch su gruppi di elementi in un RecyclerView, consentendo all'utente di selezionare più elementi ed eseguire un'azione su tutti.

Le sezioni seguenti descrivono la configurazione richiesta per il primo scenario.

Attivare la modalità azione contestuale per le singole visualizzazioni

Se vuoi richiamare la modalità azione contestuale solo quando l'utente seleziona visualizzazioni specifiche, segui questi passaggi:

  1. Implementa l'interfaccia ActionMode.Callback come mostrato nell'esempio seguente. Nei relativi metodi di callback, puoi specificare le azioni per la barra delle azioni contestuale, rispondere agli eventi di clic sugli elementi di azione e gestire altri eventi del ciclo di vita per la modalità di azione.

    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;
            }
        };
        

    Questi callback degli eventi sono quasi esattamente uguali a quelli del menu opzioni, tranne per il fatto che ognuno di questi passa anche l'oggetto ActionMode associato all'evento. Puoi utilizzare le API ActionMode per apportare varie modifiche al CAB, ad esempio rivedere il titolo e il sottotitolo con setTitle() e setSubtitle(), utile per indicare quanti elementi sono selezionati.

    L'esempio precedente imposta la variabile actionMode su null quando la modalità di azione viene eliminata. Nel passaggio successivo, scopri come viene inizializzata e come può essere utile salvare la variabile membro nell'attività o nel frammento.

  2. Chiama startActionMode() quando vuoi mostrare la barra, ad esempio quando l'utente tocca e tiene premuto sulla visualizzazione.

    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;
            }
        });
        

    Quando chiami startActionMode(), il sistema restituisce ActionMode creato. Se lo salvi in una variabile membro, puoi apportare modifiche alla barra delle azioni contestuale in risposta ad altri eventi. Nell'esempio precedente, ActionMode viene utilizzato per garantire che l'istanza ActionMode non venga ricreata se è già attiva, controllando se il membro è nullo prima di avviare la modalità Azione.

Crea un menu popup

Un&#39;immagine che mostra un menu popup nell&#39;app Gmail, ancorato al pulsante del menu extra in alto a destra.
Figura 4. Un menu popup nell'app Gmail, ancorato al pulsante del menu extra nell'angolo in alto a destra.

Un PopupMenu è un menu modale ancorato a un View. Viene visualizzato sotto la visualizzazione ancora se c'è spazio, altrimenti sopra la visualizzazione. È utile per:

  • Fornire un menu in stile overflow per le azioni relative a contenuti specifici, come le intestazioni delle email di Gmail, mostrate nella figura 4.
  • Fornendo una seconda parte di una frase di comando, ad esempio un pulsante contrassegnato con Aggiungi che produce un menu popup con diverse opzioni di Aggiungi.
  • Fornendo un menu simile a un Spinner che non mantiene una selezione persistente.

Se definisci il menu in XML, ecco come puoi mostrare il menu popup:

  1. Crea un'istanza di PopupMenu con il relativo costruttore, che accetta l'app corrente Context e View a cui è ancorato il menu.
  2. Utilizza MenuInflater per gonfiare la risorsa del menu nell'oggetto Menu restituito da PopupMenu.getMenu().
  3. Chiama il numero PopupMenu.show().

Ad esempio, ecco un pulsante che mostra un menu popup:

<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" />

L'attività può quindi mostrare il menu popup nel seguente modo:

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();
});

Il menu viene chiuso quando l'utente seleziona un elemento o tocca al di fuori dell'area del menu. Puoi ascoltare l'evento di chiusura utilizzando PopupMenu.OnDismissListener.

Gestire gli eventi di clic

Per eseguire un'azione quando l'utente seleziona una voce di menu, implementa l'interfaccia PopupMenu.OnMenuItemClickListener e registrala con PopupMenu chiamando setOnMenuItemclickListener(). Quando l'utente seleziona un elemento, il sistema chiama il onMenuItemClick() callback nella tua interfaccia.

Ciò è mostrato nel seguente esempio:

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;
    }
}

Creare un gruppo di menu

Un gruppo di menu è una raccolta di voci di menu che condividono determinate caratteristiche. Con un gruppo puoi:

Puoi creare un gruppo nidificando gli elementi <item> all'interno di un elemento <group> nella risorsa menu o specificando un ID gruppo con il metodo add().

Ecco un esempio di risorsa menu che include un gruppo:

<?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>

Gli elementi del gruppo vengono visualizzati allo stesso livello del primo elemento: tutti e tre gli elementi del menu sono fratelli. Tuttavia, puoi modificare le caratteristiche dei due elementi del gruppo facendo riferimento all'ID gruppo e utilizzando i metodi precedenti. Inoltre, il sistema non separa mai gli elementi raggruppati. Ad esempio, se dichiari android:showAsAction="ifRoom" per ogni elemento, entrambi vengono visualizzati nella barra delle azioni o nel menu di overflow delle azioni.

Utilizzare le voci di menu selezionabili

Figura 5. Un sottomenu con elementi selezionabili.

Un menu può essere utile come interfaccia per attivare e disattivare le opzioni, utilizzando una casella di controllo per le opzioni autonome o pulsanti di opzione per gruppi di opzioni mutualmente esclusive. La figura 5 mostra un sottomenu con elementi selezionabili tramite pulsanti di opzione.

Puoi definire il comportamento selezionabile per i singoli elementi di menu utilizzando l'attributo android:checkable nell'elemento <item> o per un intero gruppo con l'attributo android:checkableBehavior nell'elemento <group>. Ad esempio, tutti gli elementi di questo gruppo di menu sono selezionabili con un pulsante di opzione:

<?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>

L'attributo android:checkableBehavior accetta uno dei seguenti valori:

single
È possibile selezionare un solo elemento del gruppo, il che comporta la visualizzazione di pulsanti di opzione.
all
Tutti gli elementi possono essere selezionati, il che comporta la visualizzazione di caselle di controllo.
none
Nessun elemento è selezionabile.

Puoi applicare uno stato di selezione predefinito a un elemento utilizzando l'attributo android:checked nell'elemento <item> e modificarlo nel codice con il metodo setChecked().

Quando viene selezionato un elemento selezionabile, il sistema chiama il metodo di callback di selezione dell'elemento corrispondente, ad esempio onOptionsItemSelected(). È qui che imposti lo stato della casella di controllo, perché una casella di controllo o un pulsante di opzione non cambia stato automaticamente. Puoi eseguire una query sullo stato attuale dell'elemento, così come era prima che l'utente lo selezionasse, con isChecked() e poi impostare lo stato selezionato con setChecked(). come mostrato nell'esempio seguente:

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);
    }
}

Se non imposti lo stato selezionato in questo modo, lo stato visibile della casella di controllo o del pulsante di opzione non cambia quando l'utente lo seleziona. Quando imposti lo stato, l'attività conserva lo stato di selezione dell'elemento in modo che quando l'utente apre il menu in un secondo momento, lo stato di selezione che hai impostato sia visibile.

Aggiungere voci di menu in base a un intent

A volte vuoi che una voce di menu avvii un'attività utilizzando un Intent, che si tratti di un'attività nella tua app o in un'altra app. Quando conosci l'intent che vuoi utilizzare e hai una voce di menu specifica che lo avvia, puoi eseguire l'intent con startActivity() durante il metodo di callback on-item-selected appropriato, ad esempio il callback onOptionsItemSelected().

Tuttavia, se non hai la certezza che il dispositivo dell'utente contenga un'app che gestisce l'intent, l'aggiunta di una voce di menu che lo richiama può comportare una voce di menu non funzionante, perché l'intent potrebbe non risolversi in un'attività. Per risolvere questo problema, Android ti consente di aggiungere dinamicamente voci di menu al menu quando Android trova attività sul dispositivo che gestiscono il tuo intent.

Per aggiungere voci di menu in base alle attività disponibili che accettano un intent, procedi nel seguente modo:

  1. Definisci un intent con la categoria CATEGORY_ALTERNATIVE o CATEGORY_SELECTED_ALTERNATIVE, o entrambe, più eventuali altri requisiti.
  2. Chiama Menu.addIntentOptions(). Android cerca quindi le app che possono eseguire l'intent e le aggiunge al menu.

Se non sono installate app che soddisfano l'intent, non vengono aggiunte voci di menu.

Ciò è mostrato nel seguente esempio:

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;
}

Per ogni attività trovata che fornisce un filtro per intent corrispondente all'intent definito, viene aggiunto un elemento di menu, utilizzando il valore di android:label del filtro per intent come titolo dell'elemento di menu e l'icona dell'app come icona dell'elemento di menu. Il metodo addIntentOptions() restituisce il numero di voci di menu aggiunte.

Consenti l'aggiunta della tua attività ad altri menu

Puoi offrire i servizi della tua attività ad altre app in modo che la tua app possa essere inclusa nel menu di altre, invertendo i ruoli descritti in precedenza.

Per essere inclusa nei menu di altre app, definisci un filtro per intent come di consueto, ma includi i valori CATEGORY_ALTERNATIVE o CATEGORY_SELECTED_ALTERNATIVE o entrambi per la categoria del filtro per intent. Ciò è mostrato nel seguente esempio:

<intent-filter label="@string/resize_image">
    ...
    <category android:name="android.intent.category.ALTERNATIVE" />
    <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
    ...
</intent-filter>

Scopri di più sulla scrittura di filtri per intent in Intent e filtri per intent.