wake-up-neo.com

Android - Korrekte Verwendung von invalidateOptionsMenu ()

Ich habe viel über invalidateOptionsMenu() gesucht und weiß, was es bewirkt. Ich kann mir jedoch kein reales Beispiel vorstellen, wo diese Methode nützlich sein könnte.

Ich meine zum Beispiel, wir wollen unserer MenuItem eine neue ActionBar hinzufügen, wir können einfach das Menü von onCreateOptionsMenu(Menu menu) bekommen und es in jeder Aktion einer Schaltfläche verwenden.

Nun zu meiner eigentlichen Frage, folgt der only - Art, invalidateOptionsMenu() zu verwenden?

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

Klicken Sie auf die Schaltfläche und ein anderes Menü wird angezeigt. Klicken Sie erneut auf die Schaltfläche und das vorherige Menü wird angezeigt.

P.S. Entschuldigung für die C # -Syntax.

25
Bugs Happen

invalidateOptionsMenu() wird verwendet, um Android mitzuteilen, dass sich der Inhalt des Menüs geändert hat und das Menü neu gezeichnet werden sollte. Beispielsweise klicken Sie auf eine Schaltfläche, die zur Laufzeit ein weiteres Menüelement hinzufügt oder die Menüelementegruppe verbirgt. In diesem Fall sollten Sie invalidateOptionsMenu() aufrufen, damit das System es auf der Benutzeroberfläche neu zeichnen kann. Diese Methode ist ein Signal für das Betriebssystem, um onPrepareOptionsMenu() aufzurufen, bei dem Sie die erforderlichen Menümanipulationen implementieren . Außerdem wird OnCreateOptionsMenu() während der Erstellung der Aktivität (Fragment) nur einmal aufgerufen. Daher können Laufzeitmenüänderungen nicht von dieser Methode verarbeitet werden.

Alle finden Sie in Dokumentation :

Nachdem das System onCreateOptionsMenu () aufgerufen hat, behält es eine Instanz des Menüs, das Sie ausfüllen und onCreateOptionsMenu () nicht erneut aufrufen es sei denn, das Menü ist aus irgendeinem Grund ungültig. Sie sollten jedoch Verwenden Sie nur onCreateOptionsMenu (), um den ursprünglichen Menüzustand und .__ zu erstellen. Änderungen nicht während des Aktivitätslebenszyklus vornehmen.

Wenn Sie das Optionsmenü basierend auf aufgetretenen Ereignissen ändern möchten Während des Aktivitätslebenszyklus können Sie dies im .__ tun. onPrepareOptionsMenu () - Methode. Diese Methode übergibt Ihnen das Menu-Objekt so wie Sie es derzeit haben, können Sie es ändern, z. B. hinzufügen, entfernen oder Elemente deaktivieren (Fragmente stellen auch einen onPrepareOptionsMenu () Rückruf bereit.)

Unter Android 2.3.x und niedriger ruft das System onPrepareOptionsMenu () .__ auf. Jedes Mal, wenn der Benutzer das Optionsmenü öffnet (drückt die Menütaste).

Unter Android 3.0 und höher gilt das Optionsmenü als immer Wird geöffnet, wenn Menüelemente in der Aktionsleiste angezeigt werden. Wenn ein Ereignis Wenn Sie eine Menüaktualisierung durchführen möchten, müssen Sie .__ aufrufen. invalidateOptionsMenu (), um den Systemaufruf anzufordern onPrepareOptionsMenu ().

55
Alexander Zhak

verwenden Sie diese Option, um das neue Menü während des App-Lebenszyklus neu zu laden:

ActivityCompat.invalidateOptionsMenu(getActivity());
17
itzhar

Sie müssen die Methode onPrepareOptionsMenu() überschreiben, den Aktualisierungscode des Aktionsmenüs in derselben Methode schreiben. Wenn Sie fragment verwenden, fügen Sie setHasOptionsMenu(true); in onCreateView() hinzu.

Ich hoffe es hilft dir

2
Richa

Eine Anwendung, die ich gefunden habe, ist das Erzwingen einer Reihenfolge von Operationen zwischen onResume und onCreateOptionsMenu/onPrepareOptionsMenu. Die natürliche Reihenfolge (zumindest ab Plattform 22) scheint umzukehren, insbesondere wenn Sie Ihr Gerät neu ausrichten.

Rufen Sie invalidateOptionsMenu () in onResume () auf und Sie garantieren, dass onPrepareOptionsMenu nach onResume aufgerufen wird (es kann auch zuvor aufgerufen werden). So können Sie beispielsweise ein Menüelement aktivieren, das auf Daten basiert, die in onResume abgerufen werden.

1
Goose

Es ist alt, aber ich hoffe, das hilft jemandem in der Zukunft.

Eine Verwendung, die ich in einem realen Szenario gefunden habe:

Angenommen, Sie haben eine Liste von Elementen, die in der Datenbank gespeichert sind, und Sie haben zwei Aktivitäten:

  1. DisplayActivity: Zeigt diese Objekte an, nachdem sie aus der Datenbank abgerufen wurden.
  2. EditActivity: Dient zum Bearbeiten eines vorhandenen Elements und zum Speichern dieses Elements in einer Datenbank.

Sie haben sich für ein paar Optionen entschieden, um von DisplayActivity zu EditActivity zu wechseln:

  • Erste: Fügt einen brandneuen Gegenstand in die Datenbank ein.
  • Second: Zum Bearbeiten eines vorhandenen Elements.

Um sich nicht durch Duplizieren von Code zu wiederholen, haben Sie sich entschieden, EditActivity für beide Zwecke zu verwenden.

Daher möchten Sie das Optionsmenü an jeden Zweck anpassen. In diesem Fall würden Sie mit onCreateOptionsMenu() ein Standardoptionsmenü erstellen und es unverändert lassen, wenn es Zeit ist, ein vorhandenes Element zu bearbeiten. und invalidateOptionsMenu() es, wenn es Zeit ist, neue Elemente zu erstellen; und in diesem Fall wird onPrepareOptionsMenu() automatisch ausgelöst, um Ihr Menü anzupassen.

Beispielsweise kann das Menü Optionen eine Löschoption zum Bearbeiten eines vorhandenen Elements enthalten, die beim Hinzufügen eines neuen Elements ausgeblendet werden sollte.

0
Zain
/**
 * 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();
        }
    }
}

XML-Menübeispiel:

<?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 innerhalb eines Beispielfragments:

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

Der beste Weg, der für mich funktioniert hat, wird im Folgenden gezeigt

  1. Setzen Sie den Anfangsstatus des Menüs in onCreateOptionsMenu (...)

  2. Verwenden Sie die invalidateOptionsMenu (), um onCreateOptionsMenu (...) und onPrepareOptionsMenu (...) zu erzwingen.

  3. Rufen Sie in onPrepareOptionsMenu (...) menu.clear () auf, um alle Elemente aus dem Menü zu entfernen.

  4. In onPrepareOptionsMenu (...) platzieren Sie Ihre dynamischen Menüänderungen nach dem Löschen

Hoffe das hilft...

0

Edit: Hier ist eine bessere Antwort auf die Frage.

Eine gute Verwendung für invalidateOptionsMenu() ist, wenn wir eine ListView und Delete All MenuItem haben. Wenn die ListView leer ist, sollten wir invalidateOptionsMenu() verwenden, um die Delete All MenuItem zu entfernen.

Hier ist eine Frage zu dieser Antwort: Frage .

0
user7086724

Vom Fragmentaufruf getActivity().invalidateOptionsMenu();.

0
CoolMind