Come nascondo una voce di menu nella barra delle azioni?


346

Ho una barra delle azioni con un menuitem. Come posso nascondere / mostrare quella voce di menu?

Questo è quello che sto cercando di fare:

MenuItem item = (MenuItem) findViewById(R.id.addAction);
item.setVisible(false);
this.invalidateOptionsMenu();

Risposte:


484

Ottieni un MenuItempuntamento a tale elemento, chiamalo setVisibleper regolarne la visibilità e quindi chiama la invalidateOptionsMenu()tua attività in modo che il menu ActionBar sia regolato di conseguenza.

Aggiornamento: A MenuItemnon è una vista normale che fa parte del layout. È qualcosa di speciale, completamente diverso. Il codice ritorna nullper iteme questo sta causando l'arresto anomalo. Quello che devi invece è fare:

MenuItem item = menu.findItem(R.id.addAction);

Ecco la sequenza in cui si dovrebbe chiamare: prima chiamata invalidateOptionsMenu()e poi all'interno di onCreateOptionsMenu(Menu)ottenere un riferimento al MenuItem (chiamando menu.findItem()) e la chiamata setVisible()su di esso


Questo è quello che ho pensato inizialmente, ma questo arresta in modo anomalo l'applicazione.
Mescola Zoltán

3
@Stir Zoltán: Beh, è ​​così che fai, potresti sbagliare se si blocca l'applicazione. Ad esempio, MenuItempotresti essere nullperché stai usando getIteminvece di findItem. Non potremmo mai saperlo, senza vedere sia il codice che il registro degli arresti anomali.
K-ballo,

OK, ma come posso ottenere un riferimento al menu al di fuori del metodo onCreateOptionsMenu?
Mescola Zoltán

7
@Stir Zoltán: credo che non abbia senso con quell'ultimo commento ... Basta ottenere un riferimento alla voce del menu su onCreateOptionsMenue impostare la visibilità della voce in quel punto. Oppure mantieni il riferimento in giro fino a quando decidi se deve essere visibile o meno.
K-ballo,

33
Penso che (nella migliore delle ipotesi) questa risposta sia scarsamente formulata perché la sequenza dei passaggi è sbagliata. La sequenza corretta è prima chiamare invalidateOptionsMenu()e poi onCreateOptionsMenu(Menu)ottenere un riferimento al MenuItem(chiamando menu.findItem()) e chiamarlo setVisible(). Le risposte di suhas_sm e di P1r4nh4 presentano l'approccio corretto.
Ted Hopp,

163

Trovato un addendum a questa domanda:

Se si desidera modificare la visibilità delle voci di menu in movimento, è sufficiente impostare una variabile membro nella propria attività per ricordare che si desidera nascondere il menu e chiamare invalidateOptionsMenu()e nascondere le voci nel onCreateOptionsMenu(...)metodo sovrascritto .

//anywhere in your code
...
mState = HIDE_MENU; // setting state
invalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again
...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // inflate menu from xml
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.settings, menu);

    if (mState == HIDE_MENU)
    {
        for (int i = 0; i < menu.size(); i++)
            menu.getItem(i).setVisible(false);
    }
}

Nel mio esempio ho nascosto tutti gli oggetti.


2
Questo è esattamente quello che stavo cercando. tenere premuto MenuItem e chiamare setVisible () non sembrava fare quello che mi aspettavo (forse perché dopo stavo chiamando invalidateOptionsMenu (), quindi ricostruendo il menu), ma in entrambi i casi - funziona esattamente come speravo, grazie!
Matt,

4
Se hai intenzione di nascondere ogni oggetto, c'è un modo più semplice. Invece di scorrere ciclicamente ogni elemento qui, potresti semplicemente fare: if (HIDE_MENU) { return false; } else { getSupportMenuInflater().inflate(R.menu.menu_settings, menu); return true; }Il documento dichiara: "Devi restituire true per visualizzare il menu; se restituisci false non verrà mostrato".
w3bshark,

Inoltre, vorrei menzionare che questo approccio è molto più pulito della risposta accettata. Grazie per la condivisione!
w3bshark,

chiamando invalidateOptionMenu () chiamato onCreateOptionMenu () e gestisco le mie condizioni in onCreateOptionMenu (). Grazie per la buona risposta
user1912026

onPrepareOptionsMenu()dovrebbe essere usato per mostrare / nascondere la logica anziché onCreateOptionsMenu()come viene chiamato solo una volta, quindi non è utile se si desidera modificare le voci di menu dopo la sua inizializzazione. Quindi gonfia in onCreate, ma mostra / nascondi in onPrepare.
JCutting8,

89

Sì.

  1. È possibile impostare una bandiera / condizione.
  2. Chiama invalidateOptionsMenu()quando vuoi nascondere l'opzione. Questo chiamerà onCreateOptionsMenu().
  3. In onCreateOptionsMenu(), controlla la bandiera / condizione e mostra o nascondi nel modo seguente:
MenuItem item = menu.findItem(R.id.menu_Done);

if (flag/condition)) {
  item.setVisible(false); 
} else { }

2
Non dovrebbe essere invalidateOptionsMenuinvece di invalidateOptions?
razz,

3
Se rendi la tua bandiera un booleano, puoi semplicemente impostare la visibilità dell'oggetto sulla bandiera (o! Bandiera) se necessario. Quindi, item.setVisbility (! Flag); rende questo un liner senza condizioni if.
jwehrle,

dove viene definita la variabile "menu"?
Jonathan

È passato come parametro aonCreateOptionsMenu
suhas_sm il

l'utilizzo di questo metodo significherà che l'oggetto consuma ancora spazio e potresti finire con uno "spazio" nell'interfaccia utente dove dovrebbe essere il pulsante. L'uso di removeItem in onPrepareOptionsMenu () farà il trucco.
JCutting8,

39

Puoi chiamare questo:

MenuItem item = menu.findItem(R.id.my_item);
item.setVisible(false);

Aggiornare:

Assicurati che il tuo codice non restituisce nullper itemo può mandare in crash l'applicazione.


l'utilizzo di questo metodo significherà che l'oggetto consuma ancora spazio e potresti finire con uno "spazio" nell'interfaccia utente dove dovrebbe essere il pulsante. L'uso di removeItem in onPrepareOptionsMenu () farà il trucco.
JCutting8,

33

Stavo cercando una risposta con un po 'più di contesto. Ora che l'ho capito, aggiungerò quella risposta.

Pulsante Nascondi per impostazione predefinita nel menu XML

Per impostazione predefinita, il pulsante di condivisione sarà nascosto, come impostato da android:visible="false".

inserisci qui la descrizione dell'immagine

main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- hide share button by default -->
    <item
        android:id="@+id/menu_action_share"
        android:icon="@drawable/ic_share_white_24dp"
        android:visible="false"     
        android:title="Share"
        app:showAsAction="always"/>

    <item
        android:id="@+id/menu_action_settings"
        android:icon="@drawable/ic_settings_white_24dp"
        android:title="Setting"
        app:showAsAction="ifRoom"/>

</menu>

Mostra il pulsante nel codice

Ma il pulsante di condivisione può essere facoltativamente mostrato in base a una condizione.

inserisci qui la descrizione dell'immagine

MainActivity.java

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem shareItem = menu.findItem(R.id.menu_action_share);

    // show the button when some condition is true
    if (someCondition) {        
        shareItem.setVisible(true);
    }

    return true;
}

Guarda anche


onPrepareOptionsMenu () dovrebbe essere usato per mostrare / nascondere la logica anziché onCreateOptionsMenu () poiché viene chiamato solo una volta, quindi non è utile se si desidera modificare le voci di menu dopo la sua inizializzazione. Quindi gonfia in onCreate, ma mostra / nascondi in onPrepare, quindi usa invalidateOptionsMenu()per aggiornare il menu.
JCutting8,

24

non ha funzionato per me. Ho dovuto usare esplicitamente onPrepareOptionsMenuper impostare un oggetto invisibile.

Quindi utilizzare onCreateOptionsMenuper creare il menu e onPrepareOptionsMenuper modificare la visibilità, ecc.


1
Per me ha funzionato in entrambi i modi, ma in base ai documenti di Android onPrepareOptionsMenu sembra il posto giusto per eseguire questo tipo di operazione: "Prepara il menu delle opzioni standard dello schermo da visualizzare. Questo si chiama prima della visualizzazione del menu, ogni volta che viene mostrato È possibile utilizzare questo metodo per abilitare / disabilitare gli elementi in modo efficiente o modificare in altro modo i contenuti in modo dinamico. "
Yuval,

Sì, questo è l'ideale. onPrepareOptionsMenu () dovrebbe essere usato per mostrare / nascondere la logica anziché onCreateOptionsMenu () poiché viene chiamato solo una volta, quindi non è utile se si desidera modificare le voci di menu dopo la sua inizializzazione. Quindi gonfia in onCreate, ma mostra / nascondi in onPrepare, quindi usa invalidateOptionsMenu()per aggiornare il menu.
JCutting8,

9

Inizialmente impostare la visibilità della voce di menu su false nel file di layout del menu come segue:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:visible="false"
        android:id="@+id/action_do_something"
        android:title="@string/txt_do_something"
        app:showAsAction="always|withText"
        android:icon="@drawable/ic_done"/>
</menu>

È quindi possibile semplicemente impostare la visibilità della voce di menu su false in onCreateOptionsMenu () dopo aver gonfiato il menu.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(menu,R.menu.menu);
    MenuItem item = menu.findItem(R.id.menuItemId);
    if (item != null){
        item.setVisible(false);
    }
}

onCreateOptionsMenu non restituisce un valore booleano. La soluzione ha funzionato perfettamente però.
Joseph,

8

Prova questo:

MenuItem myitem = menu.findItem(R.id.my_item);
myitem.setVisible(false);

7

Questo ha funzionato per me sia per Activity che per Fragment

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    if (menu.findItem(R.id.action_messages) != null)
        menu.findItem(R.id.action_messages).setVisible(false);
}

1
Nel mio caso onPrepareOptionsMenu restituisce booleano, non nullo.
CoolMind

6

La risposta P1r4nh4 funziona bene, l'ho semplicemente semplificata usando un flag booleano:

public int mState = 0; //at the top of the code
//where you want to trigger the hide action
mState = 1; // to hide or mState = 0; to show
invalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again
...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // inflate menu from xml
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.settings, menu);

    if (mState == 1) //1 is true, 0 is false
    {
        //hide only option 2
            menu.getItem(2).setVisible(false);
    }
}

2
L'uso 0e 1non è una "bandiera booleana", è pseudo-booleano. inoltre, non c'è motivo di usare un vero booleano qui.
Ingo Bürk,

2
Inoltre, potresti avere diversi stati, non solo uno da nascondere e uno da mostrare. A seconda della complessità della tua app e del tuo rifiuto di scrivere nuove attività per i nuovi stati dell'app potresti avere uno stato SHOW_ALL, uno stato HIDE_ALL, ma anche uno stato HIDE_EDIT o HIDE_SHARE nel caso in cui desideri nascondere alcune parti del menu.
P1r4nh4,

4

Secondo il sito ufficiale degli sviluppatori Android, OnCreateOptionMenu (menu Menu) non è consigliato per modificare voci o icone di menu, visibilità ... ecc. In Runtime.

Dopo che il sistema chiama onCreateOptionsMenu (), mantiene un'istanza del menu popolata e non chiamerà nuovamente onCreateOptionsMenu () a meno che il menu non sia invalidato per qualche motivo. Tuttavia, è necessario utilizzare onCreateOptionsMenu () solo per creare lo stato iniziale del menu e non per apportare modifiche durante il ciclo di vita dell'attività.

Se si desidera modificare il menu delle opzioni in base agli eventi che si verificano durante il ciclo di vita delle attività, è possibile farlo nel metodo onPrepareOptionsMenu (). Questo metodo ti passa l'oggetto Menu così com'è attualmente in modo da poterlo modificare, come aggiungere, rimuovere o disabilitare gli elementi. (I frammenti forniscono anche un callback onPrepareOptionsMenu ().) - Sito ufficiale di AndroidDeveloper -

Come consigliato È possibile utilizzare questo metodo onOptionsItemSelected (voce MenuItem) per tenere traccia degli input dell'utente.

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    if (id == R.id.edit) {
        Intent intent = new Intent(this, ExampleActivity.class);
        intent.putExtra(BUNDLE_KEY, mConnection);
        startActivityForResult(intent, PICK_CHANGE_REQUEST);
        return true;
    } else if (id == R.id.delete) {
        showDialog(this);
        return true;
    }

    return super.onOptionsItemSelected(item);
}

Se è necessario modificare le voci di menu in fase di esecuzione, è possibile utilizzare onPrepareOptionsMenu (menu Menu) per modificarle

@Override
public boolean onPrepareOptionsMenu(Menu menu){

    if (Utils.checkNetworkStatus(ExampleActivity.this)) {
        menu.findItem(R.id.edit).setVisible(true);
        menu.findItem(R.id.delete).setVisible(true);
    }else {
        menu.findItem(R.id.edit).setVisible(false);
        menu.findItem(R.id.delete).setVisible(false);
    }
    return true;
} 

alcuni elementi sono sempre visibili, quindi quando io setVisible(false)per l'elemento sempre visibile, non scompare finché non faccio clic sui tre punti (Menu stesso). Se uso invalidateOptionsMenu()nelle onPrepareOptionsMenuvoci immediatamente riorganizzarsi, ma perdono le loro azioni (se clicco su qualsiasi elemento, non fa nulla).
Aliton Oliveira,

3

imposta un valore su una variabile e chiama invalidateOptionsMenu ();

per esempio

    selectedid=arg2;
            invalidateOptionsMenu();


 public boolean onPrepareOptionsMenu(Menu menu) {

    if(selectedid==1){
        menu.findItem(R.id.action_setting).setVisible(false);
        menu.findItem(R.id.action_s2).setVisible(false);
        menu.findItem(R.id.action_s3).setVisible(false);
    }
    else{
        if(selectedid==2){
            menu.findItem(R.id.action_search).setVisible(false);
            menu.findItem(R.id.action_s4).setVisible(false);
            menu.findItem(R.id.action_s5).setVisible(false);
        }
    }
    return super.onPrepareOptionsMenu(menu);
}

alcuni elementi sono sempre visibili, quindi quando io setVisible(false)per l'elemento sempre visibile, non scompare finché non faccio clic sui tre punti (Menu stesso). Se uso invalidateOptionsMenu()nelle onPrepareOptionsMenuvoci immediatamente riorganizzarsi, ma perdono le loro azioni (se clicco su qualsiasi elemento, non fa nulla).
Aliton Oliveira,

3

È possibile utilizzare toolbar.getMenu().clear();per nascondere tutte le voci di menu contemporaneamente


@Ajeet_Yadav c'è un modo per rendere visibile il menu dopo averlo cancellato?
Shawn,

3

Impostando la Visibilità di tutte le voci nel Menu, il menu della barra delle applicazioni o il menu di overflow sarà Nascondi automaticamente

Esempio

private Menu menu_change_language;

...

...

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    ...
    ...
    menu_change_language = menu;
    menu_change_language.findItem(R.id.menu_change_language)
           .setVisible(true);

    return super.onCreateOptionsMenu(menu);
}

Prima di passare ad un altro frammento usa il codice seguente:

if(menu_change_language != null){                 
    menu_change_language.findItem(R.id.menu_change_language)
       .setVisible(false);
}

2

https://stackoverflow.com/a/21215280/466363 - risposta di Look Alterno e Sufian

  • ActivityCompat.invalidateOptionsMenu () non richiamare onPrepareOptionsMenu (); aggiorna semplicemente il menu direttamente.
  • Il mio someMethod () viene chiamato da diversi punti, anche prima di onCreateOptionsMenu (), quindi devo controllare mMenu! = Null.
  • dovrebbe funzionare usando API 8

.

private Menu mMenu;
   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
       inflater.inflate(R.menu.track_fragment, menu);
       mMenu = menu;
       }
   ...
   private void someMethod() {
   ...
       if (mMenu != null) {
          MenuItem item = mMenu.findItem(R.id.new_track);
          if (item != null) {
               item.setVisible(false);
               ActivityCompat.invalidateOptionsMenu(this.getActivity());
           }
       }
   ...
   }
  • ActivityCompat.invalidateOptionsMenu () non richiamare onPrepareOptionsMenu (); aggiorna semplicemente il menu direttamente.

  • Il mio someMethod () viene chiamato da diversi punti, anche prima di onCreateOptionsMenu (), quindi devo controllare mMenu! = Null.

  • dovrebbe funzionare usando API 8

2

Se hai fatto tutto come nelle risposte sopra, ma una voce di menu è ancora visibile, controlla di fare riferimento alla risorsa unica . Ad esempio, in onCreateOptionsMenu o onPrepareOptionsMenu

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    MenuItem menuOpen = menu.findItem(R.id.menu_open);
    menuOpen.setVisible(false);
}

Ctrl + Fai clic su R.id.menu_open e verifica che esista solo in un file di menu. Nel caso in cui questa risorsa sia già utilizzata ovunque e caricata in un'attività, proverà a nascondersi lì.


2

Il modo migliore per nascondere tutti gli elementi in un menu con un solo comando è utilizzare "group" sul tuo menu xml. Basta aggiungere tutte le voci di menu che saranno nel menu di overflow all'interno dello stesso gruppo.

In questo esempio abbiamo due voci di menu che mostreranno sempre (voce normale e ricerca) e tre voci di overflow:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/someItemNotToHide1"
        android:title="ITEM"
        app:showAsAction="always" />

    <item
        android:id="@+id/someItemNotToHide2"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView|ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:title="Search"/>

    <group android:id="@+id/overFlowItemsToHide">
    <item android:id="@+id/someID" 
    android:orderInCategory="1" app:showAsAction="never" />
    <item android:id="@+id/someID2" 
    android:orderInCategory="1" app:showAsAction="never" />
    <item android:id="@+id/someID3" 
    android:orderInCategory="1" app:showAsAction="never" />
    </group>
</menu>

Quindi, sulla tua attività (preferibile su onCreateOptionsMenu), usa il comando setGroupVisible per impostare la visibilità di tutte le voci di menu su false o true.

public boolean onCreateOptionsMenu(Menu menu) {
   menu.setGroupVisible(R.id.overFlowItems, false); // Or true to be visible
}

Se si desidera utilizzare questo comando in qualsiasi altro punto della propria attività, assicurarsi di salvare la classe di menu in locale e verificare sempre se il menu è null, poiché è possibile eseguire prima di createOptionsMenu:

Menu menu;

public boolean onCreateOptionsMenu(Menu menu) {
       this.menu = menu;

}

public void hideMenus() {
       if (menu != null) menu.setGroupVisible(R.id.overFlowItems, false); // Or true to be visible       
}


1

Penso che un approccio migliore sarebbe quello di utilizzare una variabile membro per il menu, inizializzarla in onCreateOptionsMenu () e successivamente usare solo SetVisible (), senza invalidare il menu delle opzioni.


1

questo codice ha funzionato per me

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu,menu);
    if (Application.sharedPreferences.getInt("type",1) == 2)
    {
        menuItem = menu.findItem(R.id.menu_travel_orders);
        menuItem.setVisible(false);
    }
    return super.onCreateOptionsMenu(menu);
}

1

Questo approccio ha funzionato per me:

private  Menu thismenu;

if (condition)
{
   if(thismenu != null)
   {
       thismenu.findItem(R.id.menu_save).setVisible(true);
       Toast.makeText(ProfileActivity.this, 
    ""+thismenu.findItem(R.id.menu_save).getTitle(),
                Toast.LENGTH_SHORT).show();
   }else
   {
       thismenu.findItem(R.id.menu_save).setVisible(false);
   }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   getMenuInflater().inflate(R.menu.profile_menu, menu);
   thismenu = menu;

   return true;
}

1

Si sta tentando di accedere a una voce di menu da un'attività, che non ha accesso all'ambito. La chiamata per trovare la voce di menu restituirà null , poiché la vista non è associata né all'attività né al layout si sta chiamando.

Le voci di menu sono associate a voci come " Barra di navigazione " che a loro volta sono associate all'attività corrispondente.

Quindi inizializza quelle viste in attività (), quindi accedi alle voci di menu all'interno di tali viste.

Navigation navView;
navView = findViewById(R.id.navigationView);

MenuItem item = navView.getMenu().findItem(R.id.item_hosting);
item.setVisible(false);

1

uso invalidateOptionsMenu()

per chiamare onPrepareOptionsMenu(menu: Menu?)

dovresti usare onCreateOptionsMenu () solo per creare lo stato iniziale del menu e non per apportare modifiche durante il ciclo di vita dell'attività ...

Quando si verifica un evento e si desidera eseguire un aggiornamento del menu, è necessario chiamare invalidateOptionsMenu () per richiedere che la chiamata di sistema suPrepareOptionsMenu ().

https://developer.android.com/guide/topics/ui/menus


0

Android kotlin, nasconde o imposta la visibilità di una voce di menu nella barra delle azioni a livello di codice.

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    val inflater = menuInflater
    inflater.inflate(R.menu.main_menu, menu)
    val method = menu.findItem(R.id.menu_method)
    method.isVisible = false //if want to show set true
    return super.onCreateOptionsMenu(menu)
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.