Jak dynamicznie zmieniać tekst pozycji menu w Androidzie


212

Próbuję zmienić tytuł pozycji menu spoza onOptionsItemSelected(MenuItem item)metody.

Już robię następujące;

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

chciałbym jednak móc zmienić tytuł określonego elementu menu poza tą metodą.


stackoverflow.com/a/32072318/1651286 powinna być zaakceptowaną odpowiedzią
Tata Akhil

Odpowiedzi:


127

Zgodnie z sugestią JxDarkAngel, nazywając to z dowolnego miejsca w Aktywności ,

invalidateOptionsMenu();

a następnie zastąpienie:

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

jest znacznie lepszym wyborem. Użyłem odpowiedzi z https://stackoverflow.com/a/17496503/568197


Najlepsze rozwiązanie Ponieważ ta metoda zastępuje metodę Androida zamiast wymyślać koło.
Azlan Jamal

Pamiętaj, że onPrepareOptionsMenu()jest często wywoływany przez system Android, na przykład podczas wyświetlania działania i za każdym razem, gdy wyświetlane jest menu. Może to nie być bardzo wydajne, jeśli twoje menu nie zmienia się bardzo często.
Mr-IDE,

1
invalidateOptionsMenu()również zadzwoni onCreateOptionsMenu(), aby można było wprowadzić logikę aktualizacji onCreateOptionsMenu().
Mr-IDE,

Jeśli edytujesz to, aby odpowiadało
pytaniu, oznaczę

@Garbit zaktualizowano, aby użyć kodu z oryginalnego pytania!
Todd DeLand,

375

Sugerowałbym zachowanie odniesienia w ramach działania do obiektu Menu otrzymanego w onCreateOptionsMenu, a następnie użycie go do pobrania MenuItem, który wymaga zmiany, kiedy i kiedy jej potrzebujesz. Na przykład możesz zrobić coś w następujący sposób:

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

}

Alternatywnie można zastąpić opcję onPrepareOptionsMenu, aby aktualizować elementy menu za każdym razem, gdy menu jest wyświetlane.


1
Zawsze oczekuję, że Android będzie miał bardziej eleganckie rozwiązanie tego rodzaju problemów. Wydaje się, że najprostsze odpowiedzi są często najlepsze - dzięki.
Steven Wolfe

12

możesz to zrobić, utwórz globalny obiekt „Menu”, a następnie przypisz go w onCreateOptionMenu

public class ExampleActivity extends AppCompatActivity
    Menu menu;

następnie przypisz tutaj

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

Następnie użyj przypisanego obiektu Menu, aby uzyskać wymagane elementy

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

5

Utwórz metodę setOptionsTitle () i ustaw pole w swojej klasie. Jak na przykład:

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

...

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

}

Teraz, gdy menu się zapełni, zmień tytuł na dowolny status:

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

        menu.add(bedStatus);


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

Muszę być w stanie to ustawić po renderowaniu działania. Dlatego też nie w tych dwóch metodach
Garbit

Wywołaj setOptionsTitle w dowolnym momencie po wyrenderowaniu Twojej aktywności. Chyba nie rozumiem, czego chcesz, ponieważ „muszę być w stanie to ustawić po renderowaniu działania” oznacza dla mnie po wywołaniu setContent (R.layout.id), być może będziesz musiał zmienić opcje wyświetla się menu (co można zrobić za pomocą setOptionsTitle () - z dowolnej metody, w dowolnym miejscu i czasie).
Jack

Chociaż to podejście działa, nie byłoby zalecane, ponieważ obiekt Menu zarządzający menu nie będzie wiedział, kiedy tytuł się zmienił, a zatem nie może wykonać zadań, których może potrzebować, gdy tytuł się zmienia, np. Układ i podział linii .
Charles Harley

3

Lepiej użyj zastąpienia 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");
   }

Oto przykład


Rzeczywiście, zastosuj zamierzone podejście. :) Jeśli zdecydujesz się zachować lokalne odniesienie do menu, będziesz musiał się martwić o wycieki kontekstu. Albo może nie. Ale na pewno nie przy takim podejściu.
William T. Mallard

3

Używam tego kodu do kostiumowania mojego dolnego elementu nawigacyjnego

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

2

Zadeklaruj pole menu.

private Menu menu;

Poniżej znajduje się metoda 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);
}

Poniżej będzie twoja nazwa użytkownika. Albo poprzez kliknięcie przycisku, albo poprzez kod warunkowy

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

To zadziałało dla mnie.


0

Wydaje mi się, że chcesz zmienić zawartość menu w metodzie lokalnej i ta metoda jest wywoływana w dowolnym momencie, za każdym razem, gdy wystąpi zdarzenie lub w wątku interfejsu użytkownika działania.

Dlaczego nie weźmiesz wystąpienia Menu w zmiennej globalnej w onPrepareOptionsMenu, gdy jest to nadpisane i nie użyjesz tej metody. Upewnij się, że ta metoda jest wywoływana za każdym razem, gdy wystąpi zdarzenie (np. Kliknięcie przycisku) lub w wątku interfejsu użytkownika działania, module obsługi lub zadaniu asynchronicznym po wykonaniu.

Powinieneś wiedzieć z góry indeks tego elementu menu, który chcesz zmienić. Po wyczyszczeniu menu musisz napompować menu XML i zaktualizować nazwę lub ikonę elementu.


0

Dla osób, które potrzebują zestawu statycznego. Można to zrobić w pliku AndroidManifest.xml

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

Opcje Menu Tytuł Tekst


3
Pytania są dynamiczne, a nie statyczne!
EngineSense

wciąż przyszedł do wyszukiwarki Google i pomógł mi, dzięki za wysłanie
bruchowski

0

Musiałem zmienić ikonę menu dla tego fragmentu. Zmieniłem nieco odpowiedź Charlesa na to pytanie dla fragmentu:

    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);
         }
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.