Cómo cambiar el texto del elemento del menú dinámicamente en Android

212

Estoy tratando de cambiar el título de un elemento del menú desde fuera del onOptionsItemSelected(MenuItem item)método.

Ya hago lo siguiente;

public boolean onOptionsItemSelected(MenuItem item) {
  try {
    switch(item.getItemId()) {
      case R.id.bedSwitch:
        if(item.getTitle().equals("Set to 'In bed'")) {
          item.setTitle("Set to 'Out of bed'");
          inBed = false;
        } else {
          item.setTitle("Set to 'In bed'");
          inBed = true;
        }
        break;
    }
  } catch(Exception e) {
    Log.i("Sleep Recorder", e.toString());
  }
  return true;
}

sin embargo, me gustaría poder modificar el título de un elemento de menú en particular fuera de este método.

Garbit
fuente
stackoverflow.com/a/32072318/1651286 debería ser la respuesta aceptada
Akhil Dad

Respuestas:

127

Como sugirió JxDarkAngel, llamando a esto desde cualquier parte de su Actividad ,

invalidateOptionsMenu();

y luego anulando:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
  MenuItem item = menu.findItem(R.id.bedSwitch);
    if (item.getTitle().equals("Set to 'In bed'")) {
        item.setTitle("Set to 'Out of bed'");
        inBed = false;
    } else {
        item.setTitle("Set to 'In bed'");
        inBed = true;
    }
  return super.onPrepareOptionsMenu(menu);
}

Es una opción mucho mejor. Usé la respuesta de https://stackoverflow.com/a/17496503/568197

Todd DeLand
fuente
Mejor solución. Porque este anula el método de Android en lugar de reinventar la rueda.
Azlan Jamal
Solo tenga en cuenta que onPrepareOptionsMenu()el marco de Android llama con bastante frecuencia, por ejemplo, al mostrar una Actividad y cada vez que se muestra el menú. Por lo tanto, esto puede no ser muy eficiente si su menú no cambia muy a menudo.
Mr-IDE
1
invalidateOptionsMenu()también llamará onCreateOptionsMenu(), para que pueda poner la lógica de actualización onCreateOptionsMenu().
Mr-IDE
Si edita esto para que sea relevante para la pregunta, lo marcaré como la respuesta aceptada
Garbit,
¡@Garbit se actualizó para usar su código de la pregunta original!
Todd DeLand
375

Sugeriría mantener una referencia dentro de la actividad al objeto Menú que recibe en onCreateOptionsMenu y luego usarlo para recuperar el Elemento Menú que requiere el cambio cuando lo necesite. Por ejemplo, podría hacer algo similar a lo siguiente:

public class YourActivity extends Activity {

  private Menu menu;
  private String inBedMenuTitle = "Set to 'In bed'";
  private String outOfBedMenuTitle = "Set to 'Out of bed'";
  private boolean inBed = false;

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    // Create your menu...

    this.menu = menu;
    return true;
  }

  private void updateMenuTitles() {
    MenuItem bedMenuItem = menu.findItem(R.id.bedSwitch);
    if (inBed) {
      bedMenuItem.setTitle(outOfBedMenuTitle);
    } else {
      bedMenuItem.setTitle(inBedMenuTitle);
    }
  }

}

Alternativamente, puede anular onPrepareOptionsMenu para actualizar los elementos del menú cada vez que se muestra el menú.

Charles Harley
fuente
1
Siempre espero que Android tenga una solución más elegante para este tipo de problemas. Parece que las respuestas más simples son a menudo las mejores, gracias.
Steven Wolfe
12

puede hacer esto crear un objeto global "Menú" y luego asignarlo en onCreateOptionMenu

public class ExampleActivity extends AppCompatActivity
    Menu menu;

entonces asigna aquí

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    this.menu = menu;
    return true;
}

Luego, use el objeto de menú asignado para obtener los elementos requeridos

menu.findItem(R.id.bedSwitch).setTitle("Your Text");
Pranav Raut
fuente
5

Cree un método setOptionsTitle () y establezca un campo en su clase. Como:

String bedStatus = "Set to 'Out of Bed'";

...

public void setOptionsTitle(String status)
{
    bedStatus = status;

}

Ahora, cuando se llena el menú, cambie el título a cualquiera que sea su estado:

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        menu.add(bedStatus);


        // Return true so that the menu gets displayed.
        return true;
    }
Jack
fuente
Necesito poder configurarlo después de que se haya prestado la actividad. Por lo tanto, no dentro de esos dos métodos
Garbit
Llame a setOptionsTitle en cualquier momento después de que se haya prestado su actividad. Supongo que no entiendo lo que quieres porque "Necesito poder configurarlo después de que la actividad se haya procesado" significa para mí después de llamar a setContent (R.layout.id), es posible que necesites cambiar las opciones pantallas de menú (que puede hacer con setOptionsTitle () - desde cualquier método, en cualquier lugar, en cualquier momento).
Jack
Aunque este enfoque funciona, no se recomendaría, ya que el objeto Menú que administra el menú no sabrá cuándo ha cambiado el título y, por lo tanto, no puede realizar las tareas que puede necesitar cuando cambia el título, por ejemplo, el diseño y los saltos de línea .
Charles Harley
3

Es mejor usar la anulación en el menúPrepareOptionsMenu

menu.Clear ();
   if (TabActual == TabSelec.Anuncio)
   {
       menu.Add(10, 11, 0, "Crear anuncio");
       menu.Add(10, 12, 1, "Modificar anuncio");
       menu.Add(10, 13, 2, "Eliminar anuncio");
       menu.Add(10, 14, 3, "Actualizar");
   }
   if (TabActual == TabSelec.Fotos)
   {
       menu.Add(20, 21, 0, "Subir foto");
       menu.Add(20, 22, 1, "Actualizar");
   }
   if (TabActual == TabSelec.Comentarios)
   {
       menu.Add(30, 31, 0, "Actualizar");
   }

Aquí un ejemplo

JxDarkAngel
fuente
De hecho, utilice el enfoque previsto. :) Si decide mantener una referencia local al menú, creo que tendrá que preocuparse por las filtraciones de contexto. O tal vez no. Pero ciertamente no con este enfoque.
William T. Mallard
3

Utilizo este código para personalizar mi elemento de navegación inferior

BottomNavigationView navigation = this.findViewById(R.id.my_bottom_navigation);
Menu menu = navigation.getMenu();
menu.findItem(R.id.nav_wall_see).setTitle("Hello");
Oumar
fuente
2

Declara tu campo de menú.

private Menu menu;

El siguiente es el método onCreateOptionsMenu ()

public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
    try {
        getMenuInflater().inflate(R.menu.menu_main,menu);
    } catch (Exception e) {
        e.printStackTrace();
        Log.i(TAG, "onCreateOptionsMenu: error: "+e.getMessage());
    }
    return super.onCreateOptionsMenu(menu);
}

Lo siguiente será su actividad de establecimiento de nombre. Ya sea a través de un clic de botón o mediante un código condicional

public void setMenuName(){
menu.findItem(R.id.menuItemId).setTitle(/*Set your desired menu title here*/);
}

Esto funcionó para mí.

hyperCoder
fuente
0

Me parece que desea cambiar el contenido del menú dentro de un método local, y este método se llama en cualquier momento, cada vez que se produce un evento o en el hilo de la interfaz de usuario de la actividad.

¿Por qué no tomas la instancia de Menú en la variable global en onPrepareOptionsMenu cuando esto se anula y utilizas en este método tuyo? Asegúrese de que se llame a este método cada vez que se produzca un evento (como hacer clic en el botón), o en el subproceso de la interfaz de usuario de actividad, el controlador o la tarea asíncrona posterior a la ejecución.

Debe conocer de antemano el índice de este elemento del menú que desea cambiar. Después de borrar el menú, debe inflar el menú XML y actualizar el nombre o icono de su elemento.

Abhinav Saxena
fuente
0

Para las personas que necesitan el título establecido estáticamente. Esto se puede hacer en AndroidManifest.xml

<activity
    android:name=".ActivityName"
    android:label="Title Text" >
</activity>

Menú de opciones Título Texto

moberme
fuente
3
¡Las preguntas son para dinámicamente, no estáticamente!
EngineSense
todavía apareció en la búsqueda de google y me ayudó, gracias por publicar
bruchowski
0

Necesitaba cambiar el ícono de menú para el fragmento. Modifiqué un poco la respuesta de Charles a esta pregunta para el fragmento:

    private Menu top_menu;

    //...
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

       setHasOptionsMenu(true);
       //...
       rootview = inflater.inflate(R.layout.first_content,null);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.fragment_menu, menu);
        this.top_menu = menu;
    }


    // my procedure
    private void updateIconMenu() {
         if(top_menu!= null) {
             MenuItem nav_undo = top_menu.findItem(R.id.action_undo);
             nav_undo.setIcon( R.drawable.back);
         }
    }
Almaz Vildanov
fuente