So ändern Sie den Menüelementtext dynamisch in Android


212

Ich versuche, den Titel eines Menüelements von außerhalb der onOptionsItemSelected(MenuItem item)Methode zu ändern .

Ich mache schon folgendes;

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

Ich möchte jedoch in der Lage sein, den Titel eines bestimmten Menüelements außerhalb dieser Methode zu ändern.


stackoverflow.com/a/32072318/1651286 sollte die akzeptierte Antwort sein
Akhil Dad

Antworten:


127

Wie JxDarkAngel vorgeschlagen hat, rufen Sie dies von überall in Ihrer Aktivität auf .

invalidateOptionsMenu();

und dann überschreiben:

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

ist eine viel bessere Wahl. Ich habe die Antwort von https://stackoverflow.com/a/17496503/568197 verwendet


Beste Lösung. Weil diese eine Android-Methode überschreiben, anstatt das Rad neu zu erfinden.
Azlan Jamal

Beachten Sie nur, dass dies onPrepareOptionsMenu()vom Android-Framework ziemlich häufig aufgerufen wird, z. B. beim Anzeigen einer Aktivität und jedes Mal, wenn das Menü angezeigt wird. Dies ist möglicherweise nicht sehr effizient, wenn sich Ihr Menü nicht sehr oft ändert.
Mr-IDE

1
invalidateOptionsMenu()wird auch aufgerufen onCreateOptionsMenu(), so dass Sie die Aktualisierungslogik einfügen können onCreateOptionsMenu().
Mr-IDE

Wenn Sie dies bearbeiten, um für die Frage relevant zu sein, werde ich es als akzeptierte Antwort markieren
Garbit

@Garbit aktualisiert, um Ihren Code aus der ursprünglichen Frage zu verwenden!
Todd DeLand

375

Ich würde vorschlagen, innerhalb der Aktivität einen Verweis auf das Menüobjekt zu behalten, das Sie in onCreateOptionsMenu erhalten, und dieses dann zu verwenden, um das MenuItem abzurufen, für das die Änderung erforderlich ist, wenn Sie es benötigen. Sie könnten beispielsweise Folgendes tun:

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

}

Alternativ können Sie onPrepareOptionsMenu überschreiben , um die Menüelemente jedes Mal zu aktualisieren, wenn das Menü angezeigt wird.


1
Ich erwarte immer, dass Android eine elegantere Lösung für diese Art von Problemen bietet. Die einfachsten Antworten scheinen oft die besten zu sein - danke.
Steven Wolfe

12

Sie können dazu ein globales "Menü" -Objekt erstellen und es dann in onCreateOptionMenu zuweisen

public class ExampleActivity extends AppCompatActivity
    Menu menu;

dann hier zuweisen

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

Verwenden Sie später das zugewiesene Menüobjekt, um die erforderlichen Elemente abzurufen

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

5

Erstellen Sie eine setOptionsTitle () -Methode und legen Sie ein Feld in Ihrer Klasse fest. Sowie:

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

...

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

}

Wenn das Menü nun ausgefüllt ist, ändern Sie den Titel in einen beliebigen Status:

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

        menu.add(bedStatus);


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

Ich muss es einstellen können, nachdem die Aktivität gerendert wurde. Also also nicht in diesen beiden Methoden
Garbit

Rufen Sie setOptionsTitle jederzeit nach dem Rendern Ihrer Aktivität auf. Ich glaube, ich verstehe nicht, was Sie wollen, weil "Ich muss es einstellen können, nachdem die Aktivität gerendert wurde" für mich bedeutet, dass Sie nach dem Aufruf von setContent (R.layout.id) möglicherweise die Optionen ändern müssen Menüanzeigen (was Sie mit setOptionsTitle () tun können - von jeder Methode, überall und jederzeit).
Jack

Obwohl dieser Ansatz funktioniert, wird er nicht empfohlen, da das Menüobjekt, das das Menü verwaltet, nicht weiß, wann sich der Titel geändert hat, und daher nicht die Aufgaben ausführen kann, die erforderlich sind, wenn sich der Titel ändert, z. B. Layout und Zeilenumbrüche .
Charles Harley

3

Verwenden Sie besser die Überschreibung 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");
   }

Hier ein Beispiel


Verwenden Sie in der Tat den beabsichtigten Ansatz. :) Wenn Sie sich dafür entscheiden, einen lokalen Verweis auf das Menü beizubehalten, müssen Sie sich über Kontextlecks Gedanken machen, denke ich. Oder vielleicht nicht. Aber sicher nicht mit diesem Ansatz.
William T. Mallard

3

Ich benutze diesen Code, um mein unteres Navigationselement zu kostümieren

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

2

Deklarieren Sie Ihr Menüfeld.

private Menu menu;

Es folgt die Methode 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);
}

Im Folgenden finden Sie Ihre Aktivität als Namensgeber. Entweder durch Klicken auf eine Schaltfläche oder durch bedingten Code

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

Das hat bei mir funktioniert.


0

Es scheint mir, dass Sie den Inhalt des Menüs innerhalb einer lokalen Methode ändern möchten, und diese Methode wird jederzeit aufgerufen, wenn ein Ereignis auftritt oder im Thread der Aktivitäts-Benutzeroberfläche.

Warum nehmen Sie nicht die Instanz von Menu in der globalen Variablen in onPrepareOptionsMenu, wenn diese überschrieben wird, und verwenden Sie sie in Ihrer Methode. Stellen Sie sicher, dass diese Methode aufgerufen wird, wenn ein Ereignis auftritt (z. B. Klicken auf eine Schaltfläche) oder im Thread, Handler oder Async-Task der Aktivität nach der Ausführung.

Sie sollten den Index dieses Menüelements, den Sie ändern möchten, im Voraus kennen. Nach dem Löschen des Menüs müssen Sie das Menü-XML aufblasen und den Namen oder das Symbol Ihres Elements aktualisieren.


0

Für Personen, bei denen der Titel statisch festgelegt werden muss. Dies kann in der AndroidManifest.xml erfolgen

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

Optionen Menü Titel Text


3
Fragen sind für dynamisch, nicht statisch!
EngineSense

kam immer noch auf Google-Suche und half mir, danke für die Veröffentlichung
Bruchowski

0

Ich musste das Menüsymbol für das Fragment ändern. Ich habe Charles 'Antwort auf diese Frage für das Fragment ein wenig geändert:

    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);
         }
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.