web-dev-qa-db-fra.com

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" lors de la création du menu:

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

Pour ce type d'opération, je choisis généralement de ne pas modifier les éléments de 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;
}
96
Flygenring

Flygenring la réponse est correcte, mais menu.findItem () est décalé et l'appelle dans onPrepareOptionsMenu (menu Menu ) produit une mauvaise expérience utilisateur. Il est préférable d'obtenir MenuItem objet une fois 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;
    }
20
i.shadrin

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

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

6
Cheryl Simon

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 de MenuInflater car vous créez le Menu via le code, donc pas besoin de fichier XML de menu.

3
Octavian Damiean

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 apporté é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;
}
1
timv

Sur Android 3.0 et supérieur, vous devez appeler invalidateOptionsMenu () pour demander que le système appelle onPrepareOptionsMenu () . Vous pouvez ensuite modifier le menu d'options dans la méthode. Vous pouvez vérifier le Modification des éléments de menu lors de l'exécution section de la Android ici https://developer.Android.com/guide/topics/ui/menus#options-men pour plus détails.

0
Dara