Wie aktualisiere ich einen in der Aktionsleiste angezeigten Menüpunkt?

93

Ich habe eine Aktivität mit 2 Fragmenten. Beide sind ListFragments und beide tragen MenuItems zum Menü bei. Ich habe ein Menüelement, für das ich das Attribut android festgelegt habe: showAsAction, damit es als Schaltfläche in der Aktionsleiste angezeigt wird. Welches funktioniert gut.

Jetzt ist das MenuItem zustandsabhängig. Dies ist eine Menüoption zum Anhalten / Fortsetzen zum Anhalten und Fortsetzen einer Warteschlange. Mein Problem ist, dass ich nicht herausfinden kann, wie ich die ursprüngliche Statue beim Erstellen des Fragments festlegen soll.

Der Status hängt davon ab, ob die Warteschlange angehalten ist oder nicht. Ich habe also eine AsyncTask, die die Warteschlange abruft und einen Booleschen Wert (pausiert) basierend auf dem Status der Warteschlange festlegt. Ich rufe onPrepareOptionsMenu auf, um den Text für das Menüelement Pause basierend auf dem letzten bekannten Status der Warteschlange festzulegen. Dies funktioniert hervorragend, wenn ich das Menüelement im eigentlichen Menü belasse. Sie tippen auf das Menüsymbol und onPrepareOptionsMenu wird ausgelöst und das Menü wird aktualisiert, bevor es angezeigt wird.

Das Problem ist, wenn ich dasselbe MenuItem in die ActionBar (showAsAction) lege, wie kann ich die Aktualisierung erzwingen, ohne onPrepareOptionsMenu aufrufen zu müssen? Ich muss dazu in der Lage sein, da ich beim ersten Start der App eine Anfrage zum Abrufen der Warteschlange sende, die Aufgabe jedoch zurückkehrt, nachdem die ActionBar eingerichtet und angezeigt wurde. Ich habe in meinem Fragment einen Handler erstellt, der jedes Mal aufgerufen wird, wenn ich ein Warteschlangenupdate erhalte. Wie kann ich von dort aus den Text für mein MenuItem in der ActionBar aktualisieren? Ich kann anscheinend keinen Weg finden, das aktuell eingestellte Menü zu manipulieren, außer in onPrepareOptionMenu.

Rob W.

Brockoli
quelle

Antworten:

174

Option 1: Versuchen Sie es invalidateOptionsMenu(). Ich weiß nicht, ob dies ein sofortiges Neuzeichnen der Aktionsleiste erzwingen wird oder nicht.

Option 2: Überprüfen Sie, ob getActionView()für die Betroffenen etwas zurückgegeben wird MenuItem. Es ist möglich, dass showAsActioneinfach automatisch Aktionsansichten für Sie erstellt werden. Wenn ja, können Sie dies vermutlich aktivieren / deaktivieren View.

Ich kann anscheinend keinen Weg finden, das aktuell eingestellte Menü zu manipulieren, außer in onPrepareOptionMenu.

Sie können sich an das MenuObjekt halten, das Sie abgegeben haben onCreateOptionsMenu(). Zitieren der Dokumente :

Sie können das Menü (und alle daraus erstellten Elemente) sicher beibehalten und nach Bedarf Änderungen daran vornehmen, bis onCreateOptionsMenu () das nächste Mal aufgerufen wird.

CommonsWare
quelle
2
Versuchte Option # 1 und dies hat den Trick getan. Da ich versucht habe, die Benutzeroberfläche in einem Rückruf von einem separaten Thread zu aktualisieren, wurde eine Ausnahme ausgelöst, da ich mich nicht im UI-Thread befand. Um dies zu beheben, habe ich einen Handler erstellt und eine Aktualisierungsnachricht an den Handler gesendet, als mein Rückruf aufgerufen wurde. Aber letztendlich habe ich getActivity (). InvalidateOptionsMenu () verwendet, um das Menü zu aktualisieren.
Brockoli
@ Brockoli: Ah, gut! Angesichts der Formulierung der Javadocs für diese Methode war ich skeptisch, dass sie den gewünschten Effekt haben würde, obwohl es anscheinend der Grund war, warum sie sie überhaupt zu API Level 11 hinzugefügt haben. Schön zu hören, dass es für Sie funktioniert!
CommonsWare
Ich habe meinen Kopf gegen die Wand geschlagen, um das herauszufinden, und es funktioniert wie ein Zauber!
MinceMan
7
Wenn Sie die Support-Bibliothek verwenden, verwenden Sie supportInvalidateOptionsMenu()stattdessen
Tim Kist
2
@ TimKist, supportInvalidateOptionsMenu()ist jetzt veraltet; Sie können sicher verwenden invalidateOptionsMenu().
Primož Kralj
12

in meinem Fall: invalidateOptionsMenuDer Text wurde einfach auf den ursprünglichen Text zurückgesetzt, aber der direkte Zugriff auf den Menüpunkt und das Umschreiben des gewünschten Textes funktionierten ohne Probleme:

if (mnuTopMenuActionBar_ != null) {
    MenuItem mnuPageIndex = mnuTopMenuActionBar_
        .findItem(R.id.menu_magazin_pageOfPage_text);

    if (mnuPageIndex != null) {
        if (getScreenOrientation() == 1) {
            mnuPageIndex.setTitle((i + 1) + " von " + pages);
        }
        else {
            mnuPageIndex.setTitle(
                (i + 1) + " + " + (i + 2) + " " + " von " + pages);
        }
        // invalidateOptionsMenu();
    }
}

Aufgrund des folgenden Kommentars konnte ich über den folgenden Code auf den Menüpunkt zugreifen:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.magazine_swipe_activity, menu);
    mnuTopMenuActionBar_ = menu;
    return true;
}
cV2
quelle
Wie haben Sie die ActionBar-Ansicht in den Griff bekommen mnuTopMenuActionBar_?
Paul Mennega
1
Wenn die Aktionsleiste initialisiert wird, habe ich die Ansicht in einer Mitgliedsvariablen gespeichert ... wie folgt: @Override public boolean onCreateOptionsMenu (Menü menu) {MenuInflater inflater = getMenuInflater (); inflater.inflate (R.menu.magazine_swipe_activity, menu); mnuTopMenuActionBar_ = menu; return true; }
cV2
Auf diese Weise können Synchronisierungsprobleme auftreten, oder? Ich meine. Sie wissen nicht GENAU, wann onCreateOptionMenu ausgeführt wird, sodass Sie Ihren Code mit dem mnuTopMenuActionBar_nicht initialisierten Code erreichen können , oder? Wie würden Sie das umgehen?
Acrespo
Hey, wenn die Aktionsleiste verwendet wird (ja, hier ist sie), wird diese Methode immer aufgerufen, daher gibt es kein Problem damit ... (direkt beim Start der Aktivität) stackoverflow.com/questions/7705927/…
cV2
11

Um das Menü von Fragment zu aktualisieren, rufen Sie einfach an:

getActivity().invalidateOptionsMenu();
CoolMind
quelle
4

Ich habe diesen Code verwendet:

public boolean onPrepareOptionsMenu (Menu menu) {       
    MenuInflater inflater = getMenuInflater();
    TextView title  = (TextView) findViewById(R.id.title);
    menu.getItem(0).setTitle(
        getString(R.string.payFor) + " " + title.getText().toString());
    menu.getItem(1).setTitle(getString(R.string.payFor) + "...");
    return true;        
}

Und wie ein Zauber für mich gearbeitet, finden Sie OnPrepareOptionsMenu hier

FRAGEN
quelle
4
Was ist der Zweck von MenuInflater hier?
IgorGanapolsky
Das ist brillant
Steve Kamau
2

Befolgen Sie zunächst die beiden Codezeilen, um die Aktionsleistenelemente zu aktualisieren, bevor Sie eine Bedingung in oncreateOptionMenu () festlegen. Beispielsweise:

Boolean mISQuizItemSelected = false;

/**
 * Called to inflate the action bar menus
 *
 * @param menu
 *      the menu
 *
 * @return true, if successful
 */

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu items for use in the action bar

    inflater.inflate(R.menu.menu_demo, menu);

    //condition to hide the menus
    if (mISQuizItemSelected) {
        for (int i = 0; i < menu.size(); i++) {
            menu.getItem(i).setVisible(false);
        }
    }

    return super.onCreateOptionsMenu(menu);
}

/**
 * Called when the item on the action bar being selected.
 *
 * @param item
 *      menuitem being selected
 *
 * @return true if the menuitem id being selected is matched
 * false if none of the menuitems id are matched
 */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getId() == R.id.action_quiz) {
        //to navigate based on the usertype either learner or leo
        mISQuizItemSelected = true;

        ActionBar actionBar = getActionBar();
        invalidateOptionMenu();
    }
}
Saranya
quelle
1

Aus Gründen der Klarheit dachte ich, dass ein direktes Beispiel für das Ergreifen einer Ressource aus dem Folgenden gezeigt werden kann, das meiner Meinung nach zur Beantwortung dieser Frage mit einem kurzen direkten Beispiel beiträgt.

private MenuItem menuItem_;

@Override
public boolean onCreateOptionsMenu(Menu menuF) 
{
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_layout, menuF);
    menuItem_ = menuF.findItem(R.id.menu_item_identifier);
    return true;
}

In diesem Fall halten Sie zu Beginn an einer MenuItem-Referenz fest und ändern deren Status (z. B. für Änderungen des Symbolstatus) zu einem späteren Zeitpunkt.

Jay Snayder
quelle
-1

In Kotlin 1.2 rufen Sie einfach an:

invalidateOptionsMenu()

und die onCreateOptionsMenuFunktion wird erneut aufgerufen.

j_gonfer
quelle