web-dev-qa-db-fra.com

Android - Utilisation correcte de invalidateOptionsMenu ()

J'ai beaucoup cherché sur invalidateOptionsMenu() et je sais ce que ça fait. Mais je ne peux penser à aucun exemple concret dans lequel cette méthode pourrait être utile.

Je veux dire, par exemple, disons que nous voulons ajouter une nouvelle MenuItem à notre ActionBar, nous pouvons simplement obtenir le menu de onCreateOptionsMenu(Menu menu) et l'utiliser dans l'action de n'importe quel bouton.

Maintenant à ma vraie question, est-ce que suivre la seule manière d’utiliser invalidateOptionsMenu()?

bool _OtherMenu;
protected override void OnCreate (Bundle bundle)
{
    _OtherMenu = false;
    base.OnCreate (bundle);
    SetContentView (Resource.Layout.Main);
    Button button = FindViewById<Button> (Resource.Id.myButton);
    button.Click += delegate
    {
        if(_OtherMenu)
            _OtherMenu = false;
        else
            _OtherMenu = true;

        InvalidateOptionsMenu ();
    };
}

public override bool OnCreateOptionsMenu (IMenu menu)
{
    var inflater = this.SupportMenuInflater;
    if(_OtherMenu)
        inflater.Inflate (Resource.Menu.another_menu, menu);
    else
        inflater.Inflate (Resource.Menu.main_activity_menu, menu);

    return base.OnCreateOptionsMenu (menu);
}

Cliquez sur le bouton et un autre menu apparaît. Cliquez à nouveau sur le bouton et le menu précédent apparaît.

P.S. Désolé pour la syntaxe C #.

25
Bugs Happen

invalidateOptionsMenu() est utilisé pour dire Android, que le contenu du menu a changé et que le menu devrait être redessiné. Par exemple, vous cliquez sur un bouton qui ajoute un autre élément de menu à l'exécution ou masque un groupe d'éléments de menu. Dans ce cas, vous devez appeler invalidateOptionsMenu() pour que le système puisse le redessiner sur l'interface utilisateur. Cette méthode est un signal pour que le système d’appel appelle onPrepareOptionsMenu(), où vous implémentez les manipulations de menu nécessaires . De plus, OnCreateOptionsMenu() n’est appelé qu’une fois lors de la création de l’activité (fragment), les modifications du menu d’exécution ne peuvent donc pas être traitées par cette méthode.

Tous peuvent être trouvés dans documentation :

Une fois que le système a appelé onCreateOptionsMenu (), il conserve une instance du menu que vous remplissez et n'appellera plus onCreateOptionsMenu () sauf si le menu est invalidé pour une raison quelconque. Cependant, vous devriez utilisez onCreateOptionsMenu () uniquement pour créer l'état de menu initial et ne pas apporter de modifications au cours du cycle de vie de l'activité.

Si vous souhaitez modifier le menu des options en fonction des événements qui se produisent pendant le cycle de vie de l'activité, vous pouvez le faire dans le fichier méthode onPrepareOptionsMenu (). Cette méthode vous transmet l'objet Menu tel qu’il existe actuellement afin que vous puissiez le modifier, tel que ajouter, supprimer ou désactiver les éléments. (Les fragments fournissent également un rappel onPrepareOptionsMenu () )

Sur Android 2.3.x et les versions antérieures, le système appelle onPrepareOptionsMenu () chaque fois que l'utilisateur ouvre le menu des options (appuie sur le bouton Menu).

Sur Android 3.0 et les versions ultérieures, le menu des options est considéré comme étant toujours ouvrir lorsque les éléments de menu sont présentés dans la barre d’action. Quand un événement se produit et que vous souhaitez effectuer une mise à jour du menu, vous devez appeler invalidateOptionsMenu () pour demander que l'appel système appelle onPrepareOptionsMenu ().

55
Alexander Zhak

utilisez-le pour recharger un nouveau menu pendant le cycle de vie de l'application:

ActivityCompat.invalidateOptionsMenu(getActivity());
17
itzhar

Vous devez remplacer la méthode onPrepareOptionsMenu(), écrire votre menu de code de mise à jour dans la même méthode et si vous utilisez fragment, ajoutez setHasOptionsMenu(true); dans onCreateView().

J'espère que ça vous aide

2
Richa

Une utilisation que j'ai trouvée consiste à forcer un ordre d'opérations entre onResume et onCreateOptionsMenu/onPrepareOptionsMenu. L'ordre naturel (à partir de la plate-forme 22 au moins) semble basculer, en particulier lors de la réorientation de votre appareil.

Appelez invalidateOptionsMenu () dans onResume () et vous garantirez que onPrepareOptionsMenu sera appelé après onResume (il peut également être appelé auparavant). Par exemple, cela permettra d'activer un élément de menu basé sur les données récupérées dans onResume.

1
Goose
/**
 * Set a hint for whether this fragment's menu should be visible.  This
 * is useful if you know that a fragment has been placed in your view
 * hierarchy so that the user can not currently seen it, so any menu items
 * it has should also not be shown.
 *
 * @param menuVisible The default is true, meaning the fragment's menu will
 * be shown as usual.  If false, the user will not see the menu.
 */
public void setMenuVisibility(boolean menuVisible) {
    if (mMenuVisible != menuVisible) {
        mMenuVisible = menuVisible;
        if (mHasMenu && isAdded() && !isHidden()) {
            mHost.onSupportInvalidateOptionsMenu();
        }
    }
}

Exemple de menu XML:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
<item
    Android:id="@+id/action_edit"
    Android:icon="@drawable/ic_edit"
    Android:title="Edit Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_delete"
    Android:icon="@drawable/ic_delete"
    Android:title="Delete Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_check"
    Android:icon="@drawable/ic_check"
    Android:title="Check Task"
    app:showAsAction="always" />

<item
    Android:id="@+id/action_uncheck"
    Android:icon="@drawable/ic_undo"
    Android:title="Uncheck Task"
    app:showAsAction="always" />
</menu>

Code à l'intérieur d'un fragment d'échantillon:

private boolean isMenuItemChecked;

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    setMenuVisibility(false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.my_menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    try {
        menu.findItem(R.id.action_check).setVisible(!isMenuItemChecked);
        menu.findItem(R.id.action_uncheck).setVisible(isMenuItemChecked);
    }
    catch(Exception e) {
        Log.e(TAG, "onPrepareOptionsMenu error");
    }
}

public void loadUi(boolean isMenuItemChecked) {
    this.isMenuItemChecked = isMenuItemChecked;
    setMenuVisibility(true);
}
0

La meilleure façon qui a fonctionné pour moi est démontrée ci-dessous

  1. Mettez l'état initial du menu dans onCreateOptionsMenu (...)

  2. Utilisez invalidateOptionsMenu () pour forcer onCreateOptionsMenu (...) et onPrepareOptionsMenu (...).

  3. Dans onPrepareOptionsMenu (...), appelez menu.clear () pour supprimer tous les éléments du menu.

  4. Toujours dans onPrepareOptionsMenu (...), placez vos modifications de menu dynamiques après la suppression.

J'espère que cela t'aides...

0

Edit: Voici une meilleure réponse à la question.

Une bonne utilisation de invalidateOptionsMenu() est lorsque nous avons un ListView et un Delete All MenuItem. Ainsi, lorsque le ListView est vide, nous devrions utiliser invalidateOptionsMenu() pour supprimer le Delete All MenuItem.

Voici une question liée à cette réponse: Question .

0
user7086724