Come modificare dinamicamente il testo delle voci di menu in Android


212

Sto cercando di cambiare il titolo di una voce di menu al di fuori del onOptionsItemSelected(MenuItem item)metodo.

Faccio già quanto segue;

public boolean onOptionsItemSelected(MenuItem item) {
  try {
    switch(item.getItemId()) {
      case R.id.bedSwitch:
        if(item.getTitle().equals("Set to 'In bed'")) {
          item.setTitle("Set to 'Out of bed'");
          inBed = false;
        } else {
          item.setTitle("Set to 'In bed'");
          inBed = true;
        }
        break;
    }
  } catch(Exception e) {
    Log.i("Sleep Recorder", e.toString());
  }
  return true;
}

tuttavia vorrei poter modificare il titolo di una particolare voce di menu al di fuori di questo metodo.


stackoverflow.com/a/32072318/1651286 dovrebbe essere la risposta accettata
Akhil Dad

Risposte:


127

Come suggerito da JxDarkAngel, chiamandolo da qualsiasi parte della tua attività ,

invalidateOptionsMenu();

e quindi sovrascrivere:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
  MenuItem item = menu.findItem(R.id.bedSwitch);
    if (item.getTitle().equals("Set to 'In bed'")) {
        item.setTitle("Set to 'Out of bed'");
        inBed = false;
    } else {
        item.setTitle("Set to 'In bed'");
        inBed = true;
    }
  return super.onPrepareOptionsMenu(menu);
}

è una scelta molto migliore. Ho usato la risposta da https://stackoverflow.com/a/17496503/568197


Soluzione migliore. Perché questo ha la precedenza sul metodo Android invece di reinventare la ruota.
Azlan Jamal,

Basta notare che onPrepareOptionsMenu()viene chiamato abbastanza spesso dal framework Android, ad esempio quando si visualizza un'attività e ogni volta che viene visualizzato il menu. Quindi questo potrebbe non essere molto efficiente, se il tuo menu non cambia molto spesso.
Mr-IDE,

1
invalidateOptionsMenu()chiamerà anche onCreateOptionsMenu(), in modo da poter inserire la logica di aggiornamento onCreateOptionsMenu().
Mr-IDE

Se lo modifichi per essere pertinente alla domanda, lo
segnerò

@Garbit aggiornato per utilizzare il codice dalla domanda originale!
Todd DeLand l'

375

Suggerirei di mantenere un riferimento all'interno dell'attività all'oggetto Menu che ricevi in onCreateOptionsMenu e di usarlo per recuperare MenuItem che richiede la modifica come e quando ne hai bisogno. Ad esempio, potresti fare qualcosa in linea con quanto segue:

public class YourActivity extends Activity {

  private Menu menu;
  private String inBedMenuTitle = "Set to 'In bed'";
  private String outOfBedMenuTitle = "Set to 'Out of bed'";
  private boolean inBed = false;

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    // Create your menu...

    this.menu = menu;
    return true;
  }

  private void updateMenuTitles() {
    MenuItem bedMenuItem = menu.findItem(R.id.bedSwitch);
    if (inBed) {
      bedMenuItem.setTitle(outOfBedMenuTitle);
    } else {
      bedMenuItem.setTitle(inBedMenuTitle);
    }
  }

}

In alternativa, è possibile ignorare OnPrepareOptionsMenu per aggiornare le voci di menu ogni volta che viene visualizzato il menu.


1
Mi aspetto sempre che Android abbia una soluzione più elegante a questo tipo di problemi. Sembra che le risposte più semplici siano spesso le migliori - grazie.
Steven Wolfe,

12

puoi farlo creare un oggetto "Menu" globale quindi assegnarlo in onCreateOptionMenu

public class ExampleActivity extends AppCompatActivity
    Menu menu;

quindi assegnare qui

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

Quindi utilizzare l'oggetto Menu assegnato per ottenere gli elementi richiesti

menu.findItem(R.id.bedSwitch).setTitle("Your Text");

5

Crea un metodo setOptionsTitle () e imposta un campo nella tua classe. Ad esempio:

String bedStatus = "Set to 'Out of Bed'";

...

public void setOptionsTitle(String status)
{
    bedStatus = status;

}

Ora, quando il menu viene popolato, cambia il titolo in qualunque sia il tuo stato:

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        menu.add(bedStatus);


        // Return true so that the menu gets displayed.
        return true;
    }

Devo essere in grado di impostarlo dopo il rendering dell'attività. Quindi quindi non all'interno di questi due metodi
Garbit

Chiama setOptionsTitle in qualsiasi momento dopo il rendering della tua attività. Immagino di non capire cosa desideri perché "Ho bisogno di essere in grado di impostarlo dopo che l'attività è stata resa" significa per me dopo aver chiamato setContent (R.layout.id), potresti aver bisogno di cambiare quali opzioni viene visualizzato il menu (cosa che puoi fare con setOptionsTitle () - da qualsiasi metodo, ovunque, in qualsiasi momento).
Jack,

Sebbene questo approccio funzioni, non sarebbe consigliabile poiché l'oggetto Menu che gestisce il menu non saprà quando il titolo è cambiato e quindi non può eseguire le attività che potrebbe essere necessario quando il titolo cambia, ad esempio layout e interruzioni di riga .
Charles Harley,

3

È meglio utilizzare l'override onPrepareOptionsMenu

menu.Clear ();
   if (TabActual == TabSelec.Anuncio)
   {
       menu.Add(10, 11, 0, "Crear anuncio");
       menu.Add(10, 12, 1, "Modificar anuncio");
       menu.Add(10, 13, 2, "Eliminar anuncio");
       menu.Add(10, 14, 3, "Actualizar");
   }
   if (TabActual == TabSelec.Fotos)
   {
       menu.Add(20, 21, 0, "Subir foto");
       menu.Add(20, 22, 1, "Actualizar");
   }
   if (TabActual == TabSelec.Comentarios)
   {
       menu.Add(30, 31, 0, "Actualizar");
   }

Ecco un esempio


In effetti, usa l'approccio previsto. :) Se decidi di mantenere un riferimento locale al menu, dovresti preoccuparti delle perdite di contesto, penso. O forse no. Ma certamente non con questo approccio.
William T. Mallard,

3

Uso questo codice per rappresentare il mio oggetto di navigazione in basso

BottomNavigationView navigation = this.findViewById(R.id.my_bottom_navigation);
Menu menu = navigation.getMenu();
menu.findItem(R.id.nav_wall_see).setTitle("Hello");

2

Dichiara il tuo campo menu.

private Menu menu;

Di seguito è riportato il metodo onCreateOptionsMenu ()

public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
    try {
        getMenuInflater().inflate(R.menu.menu_main,menu);
    } catch (Exception e) {
        e.printStackTrace();
        Log.i(TAG, "onCreateOptionsMenu: error: "+e.getMessage());
    }
    return super.onCreateOptionsMenu(menu);
}

Di seguito sarà l'attività del tuo setter nome. Tramite un clic sul pulsante o tramite il codice condizionale

public void setMenuName(){
menu.findItem(R.id.menuItemId).setTitle(/*Set your desired menu title here*/);
}

Questo ha funzionato per me.


0

Mi sembra che tu voglia modificare il contenuto del menu all'interno di un metodo locale e questo metodo viene chiamato in qualsiasi momento, ogni volta che si verifica un evento o nel thread dell'interfaccia utente dell'attività.

Perché non prendi l'istanza di Menu nella variabile globale in onPrepareOptionsMenu quando questo viene sovrascritto e utilizzalo in questo tuo metodo. Assicurarsi che questo metodo venga chiamato ogni volta che si verifica un evento (come il clic del pulsante) o nel thread dell'interfaccia utente attività, gestore o attività asincrona post-esecuzione.

È necessario conoscere in anticipo l'indice di questa voce di menu che si desidera modificare. Dopo aver cancellato il menu, è necessario gonfiare il menu XML e aggiornare il nome o l'icona dell'articolo.


0

Per le persone che necessitano di un titolo impostato staticamente. Questo può essere fatto in AndroidManifest.xml

<activity
    android:name=".ActivityName"
    android:label="Title Text" >
</activity>

Testo del menu delle opzioni


3
Le domande sono dinamiche, non statiche!
EngineSense,

mi è venuta ancora la ricerca su google e mi ha aiutato, grazie per la pubblicazione
bruchowski,

0

Avevo bisogno di cambiare l'icona del menu per il frammento. Ho modificato un po 'la risposta di Charles a questa domanda per il frammento:

    private Menu top_menu;

    //...
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

       setHasOptionsMenu(true);
       //...
       rootview = inflater.inflate(R.layout.first_content,null);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.fragment_menu, menu);
        this.top_menu = menu;
    }


    // my procedure
    private void updateIconMenu() {
         if(top_menu!= null) {
             MenuItem nav_undo = top_menu.findItem(R.id.action_undo);
             nav_undo.setIcon( R.drawable.back);
         }
    }
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.