Comment masquer un élément de menu dans la barre d'actions?

346

J'ai une barre d'action avec un menuitem. Comment masquer / afficher cet élément de menu?

Voici ce que j'essaie de faire:

MenuItem item = (MenuItem) findViewById(R.id.addAction);
item.setVisible(false);
this.invalidateOptionsMenu();
Stir Zoltán
la source

Réponses:

484

Obtenez un MenuItempointage sur un tel élément, appelez- setVisiblele pour ajuster sa visibilité, puis appelez invalidateOptionsMenu()votre activité pour que le menu ActionBar soit ajusté en conséquence.

Mise à jour: A MenuItemn'est pas une vue régulière qui fait partie de votre mise en page. C'est quelque chose de spécial, complètement différent. Votre code revient nullpour itemet cela provoque le crash. Ce dont vous avez besoin, c'est de faire:

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

Voici la séquence dans laquelle vous devez appeler: premier appel invalidateOptionsMenu()puis à l'intérieur onCreateOptionsMenu(Menu)obtenir une référence au MenuItem (en appelant menu.findItem()) et appeler setVisible()dessus

K-ballo
la source
C'est ce à quoi j'ai pensé au début, mais cela bloque l'application.
Stir Zoltán
3
@Stir Zoltán: Eh bien, c'est comme ça que vous le faites, vous vous trompez peut-être s'il bloque l'application. Par exemple, votre MenuItempeut être nullparce que vous utilisez getItemau lieu de findItem. Nous ne pourrions jamais savoir, sans voir à la fois votre code et votre journal des plantages.
K-ballo
OK mais comment puis-je obtenir une référence au menu en dehors de la méthode onCreateOptionsMenu?
Stir Zoltán
7
@Stir Zoltán: Je pense que vous n'avez aucun sens avec ce dernier commentaire ... Obtenez simplement une référence à votre élément de menu à onCreateOptionsMenu, et définissez la visibilité de l'élément à ce point. Ou conservez la référence jusqu'à ce que vous décidiez si elle doit être visible ou non.
K-ballo
33
Je pense que (au mieux) cette réponse est mal formulée car la séquence des étapes est incorrecte. La séquence correcte consiste à appeler d'abord invalidateOptionsMenu(), puis à l'intérieur onCreateOptionsMenu(Menu)obtenir une référence à MenuItem(en appelant menu.findItem()) et appeler setVisible()dessus. Les réponses de suhas_sm et de P1r4nh4 présentent la bonne approche.
Ted Hopp
163

Trouvé un addendum à cette question:

Si vous souhaitez modifier la visibilité de vos éléments de menu lors de vos déplacements, il vous suffit de définir une variable membre dans votre activité pour vous souvenir que vous souhaitez masquer le menu et appeler invalidateOptionsMenu()et masquer les éléments dans votre onCreateOptionsMenu(...)méthode substituée .

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

Dans mon exemple, j'ai caché tous les éléments.

P1r4nh4
la source
2
C'est exactement ce que je cherchais. conserver le MenuItem et appeler setVisible () ne semblait pas faire ce que j'attendais (peut-être parce que j'appelais invalidateOptionsMenu () après, reconstruisant ainsi le menu), mais de toute façon - cela fonctionne exactement comme je l'espérais, merci!
Matt
4
Si vous souhaitez masquer chaque élément, il existe un moyen plus simple. Au lieu de parcourir chaque élément ici, vous pouvez simplement faire: if (HIDE_MENU) { return false; } else { getSupportMenuInflater().inflate(R.menu.menu_settings, menu); return true; }La documentation indique: "Vous devez retourner true pour que le menu soit affiché; si vous retournez false, il ne sera pas affiché".
w3bshark
Je voudrais également mentionner que cette approche est beaucoup plus propre que la réponse acceptée. Merci d'avoir partagé!
w3bshark
en appelant invalidateOptionMenu () onCreateOptionMenu () appelé et je gère mes conditions dans onCreateOptionMenu (). Merci pour la bonne réponse
user1912026
onPrepareOptionsMenu()doit être utilisé pour afficher / masquer la logique au lieu de onCreateOptionsMenu()car il n'est appelé qu'une seule fois, donc inutile si vous souhaitez modifier les éléments de menu après son initialisation. Alors gonflez dans onCreate, mais affichez / cachez dans onPrepare.
JCutting8
89

Oui.

  1. Vous pouvez définir un indicateur / une condition.
  2. Appelez invalidateOptionsMenu()lorsque vous souhaitez masquer l'option. Cela appelleraonCreateOptionsMenu() .
  3. Dans onCreateOptionsMenu(), vérifiez le drapeau / la condition et affichez-le ou masquez-le de la manière suivante:
MenuItem item = menu.findItem(R.id.menu_Done);

if (flag/condition)) {
  item.setVisible(false); 
} else { }
suhas_sm
la source
2
Devrait - il pas au invalidateOptionsMenulieu de invalidateOptions?
razz
3
Si vous faites de votre drapeau un booléen, vous pouvez simplement définir la visibilité de l'élément sur le drapeau (ou! Drapeau) si nécessaire. Donc, item.setVisbility (! Flag); en fait une doublure sans condition if.
jwehrle
où est définie la variable "menu"?
Jonathan
Il est passé en paramètre àonCreateOptionsMenu
suhas_sm
l'utilisation de cette méthode signifie que l'élément consomme toujours de l'espace et vous pouvez vous retrouver avec un "écart" dans votre interface utilisateur où le bouton devrait être. L'utilisation de removeItem dans onPrepareOptionsMenu () fera l'affaire.
JCutting8
39

Vous pouvez appeler cela:

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

Mise à jour:

Assurez - vous que votre code ne retourne pas nullpour itemou il peut se bloquer l'application.

elias
la source
l'utilisation de cette méthode signifie que l'élément consomme toujours de l'espace et vous pouvez vous retrouver avec un "écart" dans votre interface utilisateur où le bouton devrait être. L'utilisation de removeItem dans onPrepareOptionsMenu () fera l'affaire.
JCutting8
33

Je cherchais une réponse avec un peu plus de contexte. Maintenant que je l'ai compris, je vais ajouter cette réponse.

Masquer le bouton par défaut dans le menu xml

Par défaut, le bouton de partage sera masqué, comme défini par android:visible="false".

entrez la description de l'image ici

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>

Afficher le bouton dans le code

Mais le bouton de partage peut éventuellement être affiché en fonction de certaines conditions.

entrez la description de l'image ici

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

Voir également

Suragch
la source
onPrepareOptionsMenu () doit être utilisé pour afficher / masquer la logique au lieu de onCreateOptionsMenu () car il n'est appelé qu'une seule fois, donc inutile si vous souhaitez modifier les éléments de menu après son initialisation. Alors gonflez dans onCreate, mais affichez / cachez dans onPrepare, puis utilisez invalidateOptionsMenu()pour rafraîchir le menu.
JCutting8
24

n'a pas fonctionné pour moi. J'ai dû explicitement utiliser onPrepareOptionsMenupour définir un élément invisible.

Utilisez donc onCreateOptionsMenupour créer le menu et onPrepareOptionsMenuchanger la visibilité, etc.

hotzen
la source
1
Pour moi, cela a fonctionné dans les deux sens, mais basé sur les documents d'Android onPrepareOptionsMenu semble être le bon endroit pour faire ce type d'opération: "Préparer le menu d'options standard de l'écran à afficher. Ceci est appelé juste avant que le menu ne soit affiché, chaque fois qu'il est affiché . Vous pouvez utiliser cette méthode pour activer / désactiver efficacement des éléments ou autrement modifier dynamiquement le contenu. "
yuval
Oui, c'est idéal. onPrepareOptionsMenu () doit être utilisé pour afficher / masquer la logique au lieu de onCreateOptionsMenu () car il n'est appelé qu'une seule fois, donc inutile si vous souhaitez modifier les éléments de menu après son initialisation. Alors gonflez dans onCreate, mais affichez / cachez dans onPrepare, puis utilisez invalidateOptionsMenu()pour rafraîchir le menu.
JCutting8
9

Initialement, définissez la visibilité de l'élément de menu sur false dans le fichier de disposition de menu comme suit:

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

Vous pouvez ensuite simplement définir la visibilité de l'élément de menu sur false dans votre onCreateOptionsMenu () après avoir gonflé le 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);
    }
}
Akhila
la source
onCreateOptionsMenu ne renvoie pas de valeur booléenne. Mais la solution a parfaitement fonctionné.
Joseph
8

Essaye ça:

MenuItem myitem = menu.findItem(R.id.my_item);
myitem.setVisible(false);
mohamad sheikhi
la source
7

Cela a fonctionné pour moi à la fois de l'activité et du 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);
}
Bala Vishnu
la source
1
Dans mon cas, onPrepareOptionsMenu renvoie un booléen, pas nul.
CoolMind
6

La réponse P1r4nh4 fonctionne bien, je viens de la simplifier en utilisant un drapeau booléen:

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);
    }
}
Hiram
la source
2
Utiliser 0et 1n'est pas un "drapeau booléen", c'est pseudo-booléen. en outre, il n'y a aucune raison d'utiliser un booléen réel ici.
Ingo Bürk
2
En outre, vous pouvez avoir plusieurs états, pas un seul à masquer et un à afficher. Selon la complexité de votre application et votre refus d'écrire de nouvelles activités pour de nouveaux états d'application, vous pourriez avoir un état SHOW_ALL, un état HIDE_ALL, mais aussi un état HIDE_EDIT ou HIDE_SHARE au cas où vous voudriez masquer certaines parties de votre menu.
P1r4nh4
4

Selon le site officiel du développeur Android, OnCreateOptionMenu (menu Menu) n'est pas recommandé pour changer les éléments de menu ou les icônes, la visibilité .. etc. au moment de l'exécution.

Une fois que le système a appelé onCreateOptionsMenu (), il conserve une instance du menu que vous remplissez et n'appellera plus onCreateOptionsMenu () à moins que le menu ne soit invalidé pour une raison quelconque. Cependant, vous devez utiliser onCreateOptionsMenu () uniquement pour créer l'état de menu initial et non pour apporter des modifications au cours du cycle de vie de l'activité.

Si vous souhaitez modifier le menu d'options en fonction des événements qui se produisent pendant le cycle de vie de l'activité, vous pouvez le faire dans la méthode onPrepareOptionsMenu (). Cette méthode vous transmet l'objet Menu tel qu'il existe actuellement afin que vous puissiez le modifier, comme ajouter, supprimer ou désactiver des éléments. (Les fragments fournissent également un rappel onPrepareOptionsMenu ().) --AndroidDeveloper Official Site -

Comme recommandé Vous pouvez utiliser cette méthode onOptionsItemSelected (élément MenuItem) pour suivre les entrées utilisateur.

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

Si vous devez modifier des éléments de menu au moment de l' exécution , vous pouvez utiliser onPrepareOptionsMenu (menu Menu) pour les modifier

@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;
} 
Chanaka Fernando
la source
certains éléments sont toujours visibles, donc quand je setVisible(false)pour l'élément toujours visible, il ne disparaît que lorsque je clique sur les trois points (Menu lui-même). Si j'utilise invalidateOptionsMenu()dans onPrepareOptionsMenules éléments se réorganisent immédiatement, mais ils perdent leurs actions (si je clique sur un élément, cela ne fait rien).
Aliton Oliveira
3

définissez une valeur sur une variable et appelez invalidateOptionsMenu ();

par exemple

    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);
}
zacharia
la source
certains éléments sont toujours visibles, donc quand je setVisible(false)pour l'élément toujours visible, il ne disparaît que lorsque je clique sur les trois points (Menu lui-même). Si j'utilise invalidateOptionsMenu()dans onPrepareOptionsMenules éléments se réorganisent immédiatement, mais ils perdent leurs actions (si je clique sur un élément, cela ne fait rien).
Aliton Oliveira
3

Vous pouvez utiliser toolbar.getMenu().clear();pour masquer tous les éléments de menu à la fois

Ajeet Yadav
la source
@Ajeet_Yadav existe-t-il un moyen de rendre le menu visible après l'avoir effacé?
Shawn
3

En définissant la visibilité de tous les éléments du menu, le menu de la barre d'applications ou le menu de débordement seront masqués automatiquement.

Exemple

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

Avant de passer à un autre fragment, utilisez le code ci-dessous:

if(menu_change_language != null){                 
    menu_change_language.findItem(R.id.menu_change_language)
       .setVisible(false);
}
Hantash Nadeem
la source
2

https://stackoverflow.com/a/21215280/466363 - répondu par Look Alterno et Sufian

  • ActivityCompat.invalidateOptionsMenu () ne rappelle pas onPrepareOptionsMenu (); il suffit de mettre à jour le menu directement.
  • Mon someMethod () est appelé depuis plusieurs endroits, avant même onCreateOptionsMenu (), donc je dois vérifier mMenu! = Null.
  • devrait fonctionner en utilisant l'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 () ne rappelle pas onPrepareOptionsMenu (); il suffit de mettre à jour le menu directement.

  • Mon someMethod () est appelé depuis plusieurs endroits, avant même onCreateOptionsMenu (), donc je dois vérifier mMenu! = Null.

  • devrait fonctionner en utilisant l'API 8
Shimon Doodkin
la source
2

Si vous avez tout fait comme dans les réponses ci-dessus, mais qu'un élément de menu est toujours visible, vérifiez que vous faites référence à la ressource unique . Par exemple, dans onCreateOptionsMenu ou onPrepareOptionsMenu

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

Ctrl + Cliquez sur R.id.menu_open et vérifiez qu'il n'existe que dans un fichier de menu. Dans le cas où cette ressource est déjà utilisée n'importe où et chargée dans une activité, elle essaiera de s'y cacher.

CoolMind
la source
2

La meilleure façon de masquer tous les éléments d'un menu avec une seule commande est d'utiliser "group" sur votre menu xml. Ajoutez simplement tous les éléments de menu qui seront dans votre menu de débordement à l'intérieur du même groupe.

Dans cet exemple, nous avons deux éléments de menu qui s'afficheront toujours (élément normal et recherche) et trois éléments de débordement:

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

Ensuite, sur votre activité (préférable sur onCreateOptionsMenu), utilisez la commande setGroupVisible pour définir la visibilité de tous les éléments de menu sur false ou true.

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

Si vous souhaitez utiliser cette commande n'importe où ailleurs dans votre activité, assurez-vous d'enregistrer la classe de menu dans local et vérifiez toujours si le menu est nul, car vous pouvez l'exécuter avant 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       
}
Adriano Moutinho
la source
1

Pour ceux qui utilisent la bibliothèque Appcompat: si vos sous-classes d'activité ActionBarActivity, vous pouvez appeler supportInvalidateOptionsMenu ()

Vu ici: https://stackoverflow.com/a/19649877/1562524

RuideraJ
la source
1

Je pense qu'une meilleure approche serait d'utiliser une variable membre pour le menu, de l'initialiser dans onCreateOptionsMenu () et d'utiliser simplement setVisible () par la suite, sans invalider le menu d'options.

Catalin Clabescu
la source
1

ce code a fonctionné pour moi

@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);
}
Sai Gopi N
la source
1

Cette approche a fonctionné pour moi:

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;
}
Baba de la forêt
la source
1

Vous essayez d'accéder à un élément de menu d'une activité, qui n'a pas accès à la portée. L'appel à rechercher l'élément de menu retournera null , car la vue n'est liée ni à l'activité ni à la mise en page vous appelez.

Les éléments de menu sont liés à des éléments tels que " Barre de navigation " qui à leur tour sont liés à l'activité correspondante.

Initialisez donc ces vues dans activity (), puis accédez aux éléments de menu avec ces vues.

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

MenuItem item = navView.getMenu().findItem(R.id.item_hosting);
item.setVisible(false);
VeeyaaR
la source
1

utilisation invalidateOptionsMenu()

afin d'appeler onPrepareOptionsMenu(menu: Menu?)

vous devez utiliser onCreateOptionsMenu () uniquement pour créer l'état de menu initial et non pour apporter des modifications pendant le cycle de vie de l'activité ...

Lorsqu'un événement se produit et que vous souhaitez effectuer une mise à jour du menu, vous devez appeler invalidateOptionsMenu () pour demander que le système appelle onPrepareOptionsMenu ().

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

Dan Alboteanu
la source
0

Android kotlin, masquez ou définissez la visibilité d'un élément de menu dans la barre d'actions par programmation.

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)
}
Aftab Alam
la source