Comment modifier dynamiquement le texte d'un élément de menu dans Android

212

J'essaie de changer le titre d'un élément de menu de l'extérieur de la onOptionsItemSelected(MenuItem item)méthode.

Je fais déjà ce qui suit;

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

cependant, j'aimerais pouvoir modifier le titre d'un élément de menu particulier en dehors de cette méthode.

Garbit
la source
stackoverflow.com/a/32072318/1651286 devrait être la réponse acceptée
Akhil Dad

Réponses:

127

Comme l'a suggéré JxDarkAngel, en l'appelant de n'importe où dans votre activité ,

invalidateOptionsMenu();

puis en remplaçant:

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

est un bien meilleur choix. J'ai utilisé la réponse de https://stackoverflow.com/a/17496503/568197

Todd DeLand
la source
Meilleure solution. Parce que celui-ci remplace la méthode Android au lieu de réinventer la roue.
Azlan Jamal
Notez simplement que onPrepareOptionsMenu()le framework Android l'appelle assez souvent, par exemple lors de l'affichage d'une activité et à chaque fois que le menu est affiché. Cela peut donc ne pas être très efficace si votre menu ne change pas très souvent.
Mr-IDE
1
invalidateOptionsMenu()appellera également onCreateOptionsMenu(), afin que vous puissiez mettre la logique de mise à jour dedans onCreateOptionsMenu().
Mr-IDE
Si vous modifiez cela pour qu'il soit pertinent pour la question, je le marquerai comme la réponse acceptée
Garbit
@Garbit mis à jour pour utiliser votre code de la question d'origine!
Todd DeLand
375

Je suggère de conserver une référence dans l'activité à l'objet Menu que vous recevez dans onCreateOptionsMenu , puis de l'utiliser pour récupérer le MenuItem qui nécessite la modification au fur et à mesure que vous en avez besoin. Par exemple, vous pouvez faire quelque chose comme suit:

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

}

Alternativement, vous pouvez remplacer onPrepareOptionsMenu pour mettre à jour les éléments de menu chaque fois que le menu est affiché.

Charles Harley
la source
1
Je m'attends toujours à ce qu'Android ait une solution plus élégante à ce genre de problèmes. Il semble que les réponses les plus simples soient souvent les meilleures - merci.
Steven Wolfe
12

vous pouvez le faire créer un objet "Menu" global puis l'affecter dans onCreateOptionMenu

public class ExampleActivity extends AppCompatActivity
    Menu menu;

puis attribuez ici

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

Ensuite, utilisez plus tard l'objet Menu attribué pour obtenir les éléments requis

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

Créez une méthode setOptionsTitle () et définissez un champ dans votre classe. Tel que:

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

...

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

}

Maintenant, lorsque le menu est rempli, changez le titre en quel que soit votre statut:

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

        menu.add(bedStatus);


        // Return true so that the menu gets displayed.
        return true;
    }
Jack
la source
Je dois être en mesure de le définir après le rendu de l'activité. Donc donc pas dans ces deux méthodes
Garbit
Appelez setOptionsTitle à tout moment après le rendu de votre activité. Je suppose que je ne comprends pas ce que vous voulez parce que "je dois pouvoir le définir après que l'activité a été rendue" signifie pour moi après avoir appelé setContent (R.layout.id), vous devrez peut-être changer ce que les options affiche le menu (que vous pouvez faire avec setOptionsTitle () - à partir de n'importe quelle méthode, n'importe où, n'importe quand).
Jack
Bien que cette approche fonctionne, elle ne serait pas recommandée car l'objet Menu qui gère le menu ne saura pas quand le titre a changé et ne peut donc pas effectuer les tâches dont il peut avoir besoin lorsque le titre change, par exemple la mise en page et les sauts de ligne .
Charles Harley
3

Vous feriez mieux d'utiliser le remplacement dePrepareOptionsMenu

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

Voici un exemple

JxDarkAngel
la source
En effet, utilisez l'approche envisagée. :) Si vous décidez de conserver une référence locale au menu, vous devrez vous soucier des fuites de contexte, je pense. Ou peut être pas. Mais certainement pas avec cette approche.
William T. Mallard
3

J'utilise ce code pour costumer mon élément de navigation inférieur

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

Déclarez votre champ de menu.

private Menu menu;

Voici la méthode 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);
}

Voici votre activité de définition de nom. Soit par un clic sur le bouton, soit par un code conditionnel

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

Cela a fonctionné pour moi.

hyperCoder
la source
0

Il me semble que vous souhaitez modifier le contenu du menu dans une méthode locale, et cette méthode est appelée à tout moment, chaque fois qu'un événement se produit, ou dans le thread d'interface utilisateur d'activité.

Pourquoi ne prenez-vous pas l'instance de Menu dans la variable globale dans onPrepareOptionsMenu lorsque celle-ci est remplacée et utilisez-la dans cette méthode. Assurez-vous que cette méthode est appelée chaque fois qu'un événement se produit (comme un clic sur un bouton), ou dans le thread d'interface utilisateur d'activité, le gestionnaire ou la tâche asynchrone après exécution.

Vous devez connaître à l'avance l'index de cet élément de menu que vous souhaitez modifier. Après avoir effacé le menu, vous devez gonfler le menu XML et mettre à jour le nom ou l'icône de votre élément.

Abhinav Saxena
la source
0

Pour les personnes qui ont besoin que le titre soit défini statiquement. Cela peut être fait dans le AndroidManifest.xml

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

Texte du titre du menu Options

moberme
la source
3
Les questions sont pour dynamiquement, pas statiquement!
EngineSense
est toujours venu sur la recherche Google et m'a aidé, merci pour la publication
bruchowski
0

J'ai dû changer l'icône de menu pour le fragment. J'ai modifié un peu la réponse de Charles à cette question pour le fragment:

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