Come aggiornare una voce di menu mostrata nella ActionBar?


93

Ho un'attività che ha 2 frammenti. Entrambi sono ListFragments ed entrambi contribuiscono MenuItems al Menu. Ho un MenuItem per il quale ho impostato l'attributo android: showAsAction per visualizzarlo come pulsante sulla ActionBar. Che funziona bene.

Ora MenuItem dipende dallo stato. È un'opzione di menu Pausa / Riprendi per mettere in pausa e riprendere una coda. Il mio problema è che non riesco a capire come impostare la sua statua iniziale quando viene creato il frammento.

Il suo stato dipende dal fatto che la coda sia in pausa o meno. Quindi ho un AsyncTask che ottiene la coda e imposta un valore booleano (in pausa) in base allo stato della coda. Chiamo onPrepareOptionsMenu per impostare il testo per la voce di menu Pausa in base all'ultimo stato noto della coda e funziona benissimo se lascio MenuItem nel menu effettivo. Tocca l'icona del menu e onPrepareOptionsMenu viene attivato e il menu viene aggiornato prima di essere visualizzato.

Il problema è che, se metto lo stesso MenuItem su ActionBar (showAsAction), come posso forzare l'aggiornamento senza dover chiamare onPrepareOptionsMenu? Devo essere in grado di farlo perché al primo avvio dell'app, invio una richiesta per ottenere la coda, ma l'attività ritorna dopo che ActionBar è stata configurata e visualizzata. Ho creato un gestore nel mio frammento che viene chiamato ogni volta che ricevo un aggiornamento della coda, ma da lì, come posso aggiornare il testo per il mio MenuItem su ActionBar? Non riesco a trovare un modo per ottenere il menu attualmente impostato per manipolarlo tranne che in onPrepareOptionMenu.

Rob W.

Risposte:


174

Opzione n. 1: prova invalidateOptionsMenu(). Non so se questo forzerà o meno un ridisegno immediato della barra delle azioni.

Opzione # 2: controlla se getActionView()restituisce qualcosa per gli interessati MenuItem. È possibile che showAsActioncrei semplicemente automaticamente viste azioni per te. Se è così, puoi presumibilmente abilitarlo / disabilitarlo View.

Non riesco a trovare un modo per ottenere il menu attualmente impostato per manipolarlo tranne che in onPrepareOptionMenu.

Puoi aggrapparti Menuall'oggetto che ti è stato consegnato onCreateOptionsMenu(). Citando i documenti :

È possibile tenere in sicurezza il menu (e qualsiasi elemento creato da esso), apportando le modifiche desiderate, fino alla successiva chiamata di onCreateOptionsMenu ().


2
Ho provato l'opzione n. 1 e questo ha funzionato. Poiché stavo cercando di aggiornare l'interfaccia utente in una richiamata da un thread separato, stava generando un'eccezione poiché non ero effettivamente nel thread dell'interfaccia utente. Per risolvere questo problema, ho creato un gestore e inviato un messaggio di aggiornamento al gestore quando è stata chiamata la mia richiamata. Ma alla fine ho usato getActivity (). InvalidateOptionsMenu () per aggiornare il menu.
brockoli

@brockoli: Ah, bene! Data la formulazione dei Javadoc per quel metodo, ero scettico sul fatto che avrebbe avuto l'effetto desiderato, anche se sembrerebbe che fosse la ragione per cui l'hanno aggiunto al livello API 11 in primo luogo. Sono contento di sentire che funziona per te!
CommonsWare

Ho sbattuto la testa contro il muro cercando di capirlo e funziona a meraviglia!
MinceMan

7
Se stai usando la libreria di supporto, usa supportInvalidateOptionsMenu()invece
Tim Kist

2
@TimKist, supportInvalidateOptionsMenu()ora è deprecato; puoi tranquillamente usare invalidateOptionsMenu().
Primož Kralj

12

nel mio caso: ho invalidateOptionsMenuappena reimpostato il testo a quello originale, ma accedendo direttamente alla voce di menu e riscrivendo il testo desiderato ha funzionato senza problemi:

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

a causa del commento qui sotto, sono stato in grado di accedere alla voce di menu tramite il seguente codice:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.magazine_swipe_activity, menu);
    mnuTopMenuActionBar_ = menu;
    return true;
}

Come hai ottenuto un handle per la visualizzazione ActionBar con mnuTopMenuActionBar_?
Paul Mennega

1
quando la barra delle azioni viene inizializzata, ho salvato la vista in una variabile membro ... in questo modo: @Override public boolean onCreateOptionsMenu (Menu menu) {MenuInflater inflater = getMenuInflater (); inflater.inflate (R.menu.magazine_swipe_activity, menu); mnuTopMenuActionBar_ = menu; restituire vero; }
cV2

In questo modo, puoi avere problemi di sincronizzazione, giusto? Intendo. non sai ESATTAMENTE quando onCreateOptionMenu verrà eseguito, quindi potresti raggiungere il tuo pezzo di codice con il mnuTopMenuActionBar_non inizializzato, giusto? Come lo aggirereste?
acrespo

Hey, se si utilizza ActionBar (sì, qui è) questo metodo è sempre chiamato, quindi non c'è alcun problema con questo ... (direttamente all'avvio di attività) stackoverflow.com/questions/7705927/...
CV2

11

Per aggiornare il menu da Fragment chiama semplicemente:

getActivity().invalidateOptionsMenu();

4

Ho usato questo codice:

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

E ha funzionato come un fascino per me puoi trovare OnPrepareOptionsMenu qui


4
Qual è lo scopo di MenuInflater qui?
IgorGanapolsky

Questo è fantastico
Steve Kamau

2

Per prima cosa, segui le due righe di codice per aggiornare gli elementi della barra delle azioni prima di impostare una condizione in oncreateOptionMenu (). Per esempio:

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

1

Per chiarezza, ho pensato che un esempio diretto di afferrare una risorsa può essere mostrato da quanto segue che penso contribuisca alla risposta a questa domanda con un rapido esempio diretto.

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 questo caso tieni un riferimento MenuItem all'inizio e quindi ne modifichi lo stato (ad esempio per i cambiamenti di stato dell'icona) in un dato momento successivo.


-1

In Kotlin 1.2 chiama semplicemente:

invalidateOptionsMenu()

e la onCreateOptionsMenufunzione verrà richiamata di nuovo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.