44 votes

Comment puis-je modifier un MenuItem dans le menu Options sur Android?

J'ai un menu d'options sur mon Activity avec un MenuItem "Démarrer". Lorsque ce MenuItem est sélectionné, je voudrais modifier le menu pour qu'il contienne un MenuItem "Stop". Et enfin, lorsque "Stop" est sélectionné, je voudrais revenir à "Start".

Voici des parties de mon code qui ne fonctionnent pas. J'ai "Start" et "Stop" répertoriés dans mymenu.xml Je devrais probablement supprimer "stop" lorsque le menu est créé:

 public class MyActivity extends Activity {
    private boolean isStarted = false;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        menu.removeItem(R.id.stop);
        inflater.inflate(R.menu.mymenu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.start:
            isStarted = true;
            return true;
        case R.id.stop:
            isStarted = false;
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if(isStarted) {
            menu.removeItem(R.id.start);
            menu.add(R.id.stop);
        } else {
            menu.removeItem(R.id.stop);
            menu.add(R.id.start);
        }
        return true;
    }
}
 

98voto

Flygenring Points 1472

Pour ce type d'opération, je choisis généralement de ne pas modifier les éléments du menu, mais de masquer ceux dont vous n'avez pas besoin:

 @Override
public boolean onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    menu.findItem(R.id.start).setVisible(!isStarted);
    menu.findItem(R.id.stop).setVisible(isStarted);
    return true;
}
 

21voto

i.shadrin Points 81

La réponse de Flygenring est correcte, mais menu.findItem () est décalé et l'appeler dans onPrepareOptionsMenu (menu Menu) produit une mauvaise expérience utilisateur. Il est beaucoup mieux d'obtenir une fois l'objet MenuItem lors de la création du menu, puis d'appeler setVisible à chaque fois que le menu apparaît à l'écran:

     MenuItem mDynamicMenuItem;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        // Get dynamic menu item
        mDynamicMenuItem = menu.findItem(R.id.menu_item);
        return true;
    }

    // Prepare the Screen's standard options menu to be displayed. This is called right 
    // before the menu is shown, every time it is shown. You can use this method to
    // efficiently enable/disable items or otherwise dynamically modify the contents.
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        // Here is just a good place to update item
        mDynamicMenuItem.setVisible(isVisible);
        return true;
    }
 

6voto

Cheryl Simon Points 25259

Vous devrez probablement appeler super.onPrepareOptionsMenu une fois vos modifications terminées. De la documentation :

Les classes dérivées doivent toujours appeler l'implémentation de la classe de base.

3voto

Octavian Damiean Points 20620

J'ai la solution. Vous supprimez essentiellement le MenuItem lorsque vous appelez removeItem() supprimant ainsi également la référence. L'utilisation de ce code fonctionne.

 private boolean isStarted = false;

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case 1:
        isStarted = true;
        return true;
    case 0:
        isStarted = false;
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {

    if(isStarted) {
        menu.removeItem(1);
        menu.add(0, 0, 0, "Stop");
    } else {
        menu.removeItem(0);
        menu.add(0, 1, 0, "Start");
    }

    return super.onPrepareOptionsMenu(menu);
}
 

Vous devez recréer le MenuItem . C'est aussi la raison du label false . En fait, vous n'avez pas besoin du MenuInflater car vous créez le Menu via le code, donc pas besoin de fichier XML de menu.

1voto

tjv Points 652

merci pour l'info dans ce post car elle a résolu mon problème de fausses étiquettes dans mon menu. J'ai dû le modifier légèrement et avoir le code final qui fonctionne bien comme suit dans l'espoir qu'il économise du temps et de la frustration à quelqu'un d'autre. C'est une solution légèrement différente, mais le principal changement que j'ai fait était le .setVisible à True ou False, à part que la solution i.shadrins était la mieux adaptée à mes besoins.

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

    if(loggedIn) 
    {
        logIn.setVisible(false);
        logOut.setVisible(true);
    } 
    else 
    {
        logIn.setVisible(true);
        logOut.setVisible(false);
    }
    return true;
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    logIn = menu.findItem(R.id.loggedOut);
    logOut = menu.findItem(R.id.loggedIn);
    return true;
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X