¿Cómo oculto un elemento del menú en la barra de acción?

346

Tengo una barra de acción con un elemento de menú. ¿Cómo puedo ocultar / mostrar ese elemento del menú?

Esto es lo que estoy tratando de hacer:

MenuItem item = (MenuItem) findViewById(R.id.addAction);
item.setVisible(false);
this.invalidateOptionsMenu();
Revuelva Zoltán
fuente

Respuestas:

484

Obtener una MenuItemque apunta a dicho artículo, llamada setVisibleen él para ajustar su visibilidad y luego llamar invalidateOptionsMenu()a sus actividades en lo que el menú Barra de acciones se ajusta en consecuencia.

Actualización: A MenuItemno es una vista normal que es parte de su diseño. Es algo especial, completamente diferente. Sus declaraciones de código nullpara itemy que está causando el accidente. Lo que necesitas en cambio es hacer:

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

Aquí está la secuencia en la que debe llamar: primero llame invalidateOptionsMenu()y luego onCreateOptionsMenu(Menu)obtenga una referencia al MenuItem (llamando menu.findItem()) y llame setVisible()a él

K-Ballo
fuente
Esto es lo que pensé inicialmente, pero bloquea la aplicación.
Revuelva Zoltán
3
@Stir Zoltán: Bueno, así es como lo haces, es posible que lo estés haciendo mal si bloquea la aplicación. Por ejemplo, MenuItempuede ser nullporque está usando en getItemlugar de findItem. Nunca podríamos saberlo sin ver su código y el registro de fallas.
K-balloon
OK, pero ¿cómo puedo obtener una referencia al menú fuera del método onCreateOptionsMenu?
Agitar Zoltán
77
@Stir Zoltán: Creo que no tiene sentido con ese último comentario ... Simplemente obtenga una referencia a su elemento de menú en onCreateOptionsMenu, y configure la visibilidad del elemento en ese punto. O mantenga la referencia hasta que decida si debe ser visible o no.
K-balloon
33
Creo que (en el mejor de los casos) esta respuesta está mal redactada porque la secuencia de pasos es incorrecta. La secuencia correcta es llamar primero invalidateOptionsMenu()y luego onCreateOptionsMenu(Menu)obtener una referencia al MenuItem(llamando menu.findItem()) y llamarlo setVisible(). Las respuestas de suhas_sm y de P1r4nh4 presentan el enfoque correcto.
Ted Hopp
163

Encontré un apéndice a esta pregunta:

Si desea cambiar la visibilidad de sus elementos de menú sobre la marcha, solo necesita establecer una variable miembro en su actividad para recordar que desea ocultar el menú y llamar invalidateOptionsMenu()y ocultar los elementos en su onCreateOptionsMenu(...)método anulado .

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

En mi ejemplo, he escondido todos los elementos.

P1r4nh4
fuente
2
Esto es exactamente lo que he estado buscando. mantener el MenuItem y llamar a setVisible () no parecía hacer lo que esperaba (tal vez porque estaba llamando invalidateOptionsMenu () después, reconstruyendo el menú), pero de cualquier manera, esto funciona exactamente como esperaba, ¡gracias!
Matt
44
Si vas a ocultar cada elemento, hay una manera más fácil. En lugar de recorrer cada elemento aquí, puede hacer lo siguiente: if (HIDE_MENU) { return false; } else { getSupportMenuInflater().inflate(R.menu.menu_settings, menu); return true; }Los documentos indican: "Debe devolver verdadero para que se muestre el menú; si devuelve falso, no se mostrará".
w3bshark
Además, me gustaría mencionar que este enfoque es mucho más limpio que la respuesta aceptada. ¡Gracias por compartir!
w3bshark
llamando a invalidateOptionMenu () onCreateOptionMenu () llamado y manejo mis condiciones en onCreateOptionMenu (). Gracias por una buena respuesta
user1912026
onPrepareOptionsMenu()debe usarse para mostrar / ocultar lógica en lugar de onCreateOptionsMenu()como solo se llama una vez, por lo que no es útil si desea cambiar los elementos del menú después de su inicialización. Por lo tanto, inflar en onCreate, pero mostrar / ocultar en onPrepare.
JCutting8
89

Si.

  1. Puede establecer una bandera / condición.
  2. Llame invalidateOptionsMenu()cuando quiera ocultar la opción. Esto llamaráonCreateOptionsMenu() .
  3. En onCreateOptionsMenu(), verifique la bandera / condición y muéstrela u ocúltela de la siguiente manera:
MenuItem item = menu.findItem(R.id.menu_Done);

if (flag/condition)) {
  item.setVisible(false); 
} else { }
suhas_sm
fuente
2
¿No debería ser en invalidateOptionsMenulugar de invalidateOptions?
razz
3
Si hace que su bandera sea booleana, puede establecer la visibilidad del elemento a la bandera (o! Bandera) si es necesario. Entonces, item.setVisbility (! Flag); hace de este un revestimiento sin condiciones.
Jwehrle
¿Dónde se define la variable "menú"?
Jonathan
Se pasa como parámetro aonCreateOptionsMenu
suhas_sm
el uso de este método significará que el elemento aún consume espacio y puede terminar con un "espacio" en su interfaz de usuario donde debería estar el botón. Usar removeItem en onPrepareOptionsMenu () hará el truco.
JCutting8
39

Puedes llamar a esto:

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

Actualizar:

Asegúrese de que su código no regresa nullpara itemo puede bloquear la aplicación.

elias
fuente
el uso de este método significará que el elemento aún consume espacio y puede terminar con un "espacio" en su interfaz de usuario donde debería estar el botón. Usar removeItem en onPrepareOptionsMenu () hará el truco.
JCutting8
33

Estaba buscando una respuesta con un poco más de contexto. Ahora que lo he descubierto, agregaré esa respuesta.

Ocultar botón por defecto en el menú xml

Por defecto, el botón compartir estará oculto, según lo establecido por android:visible="false".

ingrese la descripción de la imagen aquí

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>

Mostrar botón en código

Pero el botón compartir puede mostrarse opcionalmente en función de alguna condición.

ingrese la descripción de la imagen aquí

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

Ver también

Suragch
fuente
onPrepareOptionsMenu () debe usarse para mostrar / ocultar lógica en lugar de onCreateOptionsMenu () ya que solo se llama una vez, por lo que no es útil si desea cambiar los elementos del menú después de su inicialización. Por lo tanto, infle en onCreate, pero muestre / oculte en onPrepare, luego use invalidateOptionsMenu()para actualizar el menú.
JCutting8
24

No funcionó para mí. Tuve que usar explícitamente onPrepareOptionsMenupara establecer un elemento invisible.

Así que úselo onCreateOptionsMenupara crear el menú y onPrepareOptionsMenucambiar la visibilidad, etc.

hotzen
fuente
1
Para mí funcionó en ambos sentidos, pero según los documentos de Android onPrepareOptionsMenu parece ser el lugar correcto para realizar este tipo de operación: "Prepare el menú de opciones estándar de la pantalla para que se muestre. Esto se llama justo antes de que se muestre el menú, cada vez que se muestra . Puede usar este método para habilitar / deshabilitar elementos de manera eficiente o modificar dinámicamente el contenido ".
yuval
Si, esto es ideal. onPrepareOptionsMenu () debe usarse para mostrar / ocultar lógica en lugar de onCreateOptionsMenu () ya que solo se llama una vez, por lo que no es útil si desea cambiar los elementos del menú después de su inicialización. Por lo tanto, infle en onCreate, pero muestre / oculte en onPrepare, luego use invalidateOptionsMenu()para actualizar el menú.
JCutting8
9

Inicialmente establezca la visibilidad del elemento del menú en falso en el archivo de diseño del menú de la siguiente manera:

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

Luego, simplemente puede establecer la visibilidad del elemento del menú en falso en su onCreateOptionsMenu () después de inflar el menú.

@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
fuente
onCreateOptionsMenu no devuelve un valor booleano. Sin embargo, la solución funcionó perfectamente.
Joseph
8

Prueba esto:

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

Esto funcionó para mí tanto de Actividad como de Fragmento

@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
fuente
1
En mi caso, onPrepareOptionsMenu devuelve boolean, no anulado.
CoolMind
6

La respuesta P1r4nh4 funciona bien, simplemente la simplifiqué usando una bandera booleana:

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
fuente
2
Usar 0y 1no es una "bandera booleana", es pseudobooleana. Además, no hay ninguna razón para usar un booleano real aquí.
Ingo Bürk
2
Además, podría tener varios estados, no solo uno para ocultar y otro para mostrar. Dependiendo de la complejidad de su aplicación y su negativa a escribir nuevas actividades para los nuevos estados de la aplicación, es posible que tenga un estado SHOW_ALL, un estado HIDE_ALL, pero también un estado HIDE_EDIT o HIDE_SHARE en caso de que desee ocultar ciertas partes de su menú.
P1r4nh4
4

De acuerdo con el sitio oficial de Android Developer, OnCreateOptionMenu (menú de menú) no se recomienda para cambiar elementos de menú o iconos, visibilidad ... etc. en tiempo de ejecución.

Después de que el sistema llama a onCreateOptionsMenu (), retiene una instancia del Menú que completa y no volverá a llamar a onCreateOptionsMenu () a menos que el menú se invalide por alguna razón. Sin embargo, debe usar onCreateOptionsMenu () solo para crear el estado del menú inicial y no para realizar cambios durante el ciclo de vida de la actividad.

Si desea modificar el menú de opciones en función de los eventos que ocurren durante el ciclo de vida de la actividad, puede hacerlo en el método onPrepareOptionsMenu (). Este método le pasa el objeto Menú tal como existe actualmente para que pueda modificarlo, como agregar, eliminar o deshabilitar elementos. (Los fragmentos también proporcionan una devolución de llamada onPrepareOptionsMenu ().) --Sitio oficial de AndroidDeveloper -

Según lo recomendado Puede usar este método onOptionsItemSelected (elemento MenuItem) para rastrear las entradas del usuario.

@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 necesita cambiar elementos de menú en tiempo de ejecución, puede usar onPrepareOptionsMenu (menú de menú) para cambiarlos

@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
fuente
algunos elementos son siempre visibles, por lo que cuando setVisible(false)aparece el elemento siempre visible, no desaparece hasta que hago clic en los tres puntos (Menú en sí). Si lo uso invalidateOptionsMenu()en onPrepareOptionsMenulos elementos, se reorganiza inmediatamente, pero pierden sus acciones (si hago clic en cualquier elemento, no hace nada).
Aliton Oliveira
3

establecer un valor a una variable y llamar a invalidateOptionsMenu ();

por ejemplo

    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
fuente
algunos elementos siempre están visibles, por lo que cuando setVisible(false)aparece el elemento siempre visible, no desaparece hasta que hago clic en los tres puntos (Menú en sí). Si lo uso invalidateOptionsMenu()en onPrepareOptionsMenulos elementos, se reorganiza inmediatamente, pero pierden sus acciones (si hago clic en cualquier elemento, no hace nada).
Aliton Oliveira
3

Puede usar toolbar.getMenu().clear();para ocultar todos los elementos del menú a la vez

Ajeet Yadav
fuente
@Ajeet_Yadav, ¿hay alguna forma de hacer que el menú sea visible después de borrarlo?
Shawn
3

Al configurar la visibilidad de todos los elementos en el menú, el menú de la barra de aplicaciones o el menú de desbordamiento se ocultará automáticamente

Ejemplo

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

Antes de ir a otro fragmento, use el siguiente código:

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

https://stackoverflow.com/a/21215280/466363 - respondido por Look Alterno y Sufian

  • ActivityCompat.invalidateOptionsMenu () no devuelve la llamada a OnPrepareOptionsMenu (); solo actualiza el menú directamente.
  • Mi someMethod () recibe una llamada desde varios lugares, incluso antes de onCreateOptionsMenu (), así que debo verificar mMenu! = Null.
  • debería funcionar 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 () no devuelve la llamada a OnPrepareOptionsMenu (); solo actualiza el menú directamente.

  • Mi someMethod () recibe una llamada desde varios lugares, incluso antes de onCreateOptionsMenu (), así que debo verificar mMenu! = Null.

  • debería funcionar usando API 8
Shimon Doodkin
fuente
2

Si hizo todo como en las respuestas anteriores, pero un elemento del menú aún está visible, verifique que haga referencia al recurso único . Por ejemplo, en onCreateOptionsMenu o onPrepareOptionsMenu

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

Ctrl + Haga clic en R.id.menu_open y verifique que solo exista en un archivo de menú. En caso de que este recurso ya se use en cualquier lugar y se cargue en una actividad, intentará esconderse allí.

CoolMind
fuente
2

La mejor manera de ocultar todos los elementos en un menú con un solo comando es usar "group" en su menú xml. Simplemente agregue todos los elementos de menú que estarán en su menú de desbordamiento dentro del mismo grupo.

En este ejemplo, tenemos dos elementos de menú que siempre se mostrarán (elemento normal y búsqueda) y tres elementos de desbordamiento:

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

Luego, en su actividad (preferible en onCreateOptionsMenu), use el comando setGroupVisible para establecer la visibilidad de todos los elementos del menú en falso o verdadero.

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

Si desea utilizar este comando en cualquier otro lugar de su actividad, asegúrese de guardar la clase de menú en local y compruebe siempre si el menú es nulo, porque puede ejecutar antes de 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
fuente
1

Creo que un mejor enfoque sería usar una variable miembro para el menú, inicializarla en onCreateOptionsMenu () y simplemente usar setVisible () después, sin invalidar el menú de opciones.

Catalin Clabescu
fuente
1

este código me funcionó

@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
fuente
1

Este enfoque funcionó para mí:

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 del bosque
fuente
1

Está intentando acceder a un elemento del menú desde una actividad, que no tiene acceso al alcance. La llamada para encontrar el elemento del menú devolverá nulo , porque la vista no está vinculada ni con la actividad ni el diseño que está llamando.

Los elementos del menú están vinculados con elementos como " Barra de navegación " que a su vez están vinculados con la actividad correspondiente.

Inicialice esas vistas en la actividad () y luego acceda a los elementos del menú dentro de esas vistas.

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

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

utilizar invalidateOptionsMenu()

para llamar onPrepareOptionsMenu(menu: Menu?)

debe usar onCreateOptionsMenu () solo para crear el estado del menú inicial y no para realizar cambios durante el ciclo de vida de la actividad ...

Cuando se produce un evento y desea realizar una actualización del menú, debe llamar a invalidateOptionsMenu () para solicitar que el sistema llame a onPrepareOptionsMenu ().

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

Dan Alboteanu
fuente
0

Android kotlin, oculta o establece la visibilidad de un elemento del menú en la barra de acción mediante programación.

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
fuente