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.


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


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


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

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

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


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

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.


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.


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


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);
         }
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.