Como alterar o texto do item de menu dinamicamente no Android


212

Estou tentando alterar o título de um item de menu de fora do onOptionsItemSelected(MenuItem item)método.

Eu já faço o seguinte;

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

no entanto, eu gostaria de poder modificar o título de um item de menu específico fora deste método.


Respostas:


127

Como o JxDarkAngel sugeriu, chamando isso de qualquer lugar da sua Atividade ,

invalidateOptionsMenu();

e então substituindo:

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

é uma escolha muito melhor. Eu usei a resposta de https://stackoverflow.com/a/17496503/568197


Melhor solução. Porque este substitui o método android em vez de reinventar a roda.
— Azlan Jamal

Observe que isso onPrepareOptionsMenu()é chamado com bastante frequência pela estrutura do Android, por exemplo, ao exibir uma Atividade e toda vez que o menu é exibido. Portanto, isso pode não ser muito eficiente, se o menu não mudar com muita frequência.
— Mr-IDE

1
invalidateOptionsMenu()também chamará onCreateOptionsMenu(), para que você possa inserir a lógica de atualização onCreateOptionsMenu().
— Mr-IDE

Se você editar este seja relevante para a questão eu vou marcá-lo como a resposta aceita
— Garbit

@Garbit atualizado para usar seu código da pergunta original!
— Todd DeLand

375

Sugiro que você mantenha uma referência dentro da atividade ao objeto Menu recebido no onCreateOptionsMenu e, em seguida, use-o para recuperar o MenuItem que requer a alteração quando necessário. Por exemplo, você pode fazer algo como:

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

}

Como alternativa, você pode substituir o menu Preferências de opções para atualizar os itens de menu sempre que o menu for exibido.


1
Eu sempre espero que o Android tenha uma solução mais elegante para esse tipo de problema. Parece que as respostas mais simples costumam ser as melhores - obrigado.
— Steven Wolfe

12

você pode criar um objeto global "Menu" e atribuí-lo no onCreateOptionMenu

public class ExampleActivity extends AppCompatActivity
    Menu menu;

então atribua aqui

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

Depois, use o objeto de menu atribuído para obter os itens necessários

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

5

Crie um método setOptionsTitle () e defina um campo na sua classe. Tal como:

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

...

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

}

Agora, quando o menu for preenchido, altere o título para qualquer que seja seu status:

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

        menu.add(bedStatus);


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

Preciso defini-lo após a atividade ter sido renderizada. Portanto, portanto, não dentro desses dois métodos
— Garbit

Chame setOptionsTitle a qualquer momento após a renderização da sua atividade. Acho que não estou entendendo o que você quer, porque "Preciso defini-lo após a atividade ter sido renderizada" significa para mim depois que você chama setContent (R.layout.id), pode ser necessário alterar as opções o menu é exibido (o que você pode fazer com setOptionsTitle () - de qualquer método, em qualquer lugar, a qualquer momento).
— Jack

Embora essa abordagem funcione, não seria recomendável, pois o objeto Menu que gerencia o menu não saberá quando o título foi alterado e, portanto, não poderá executar as tarefas necessárias quando o título for alterado, por exemplo, layout e quebras de linha .
— Charles Harley

3

É melhor usar a substituição no menuPrepareOptions

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

Aqui um exemplo


De fato, use a abordagem pretendida. :) Se você decidir manter uma referência local ao menu, precisará se preocupar com vazamentos de contexto. Ou talvez não. Mas certamente não com essa abordagem.
— William T. Mallard

3

Eu uso esse código para costurar meu item de navegação inferior

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

2

Declare o seu campo de menu.

private Menu menu;

A seguir está o método 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);
}

A seguir, apresentamos sua atividade de criação de nomes. Através de um clique no botão ou de um código condicional

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

Isso funcionou para mim.


0

Parece-me que você deseja alterar o conteúdo do menu dentro de um método local, e esse método é chamado a qualquer momento, sempre que um evento ocorre ou no segmento da interface do usuário da atividade.

Por que você não pega a instância de Menu na variável global no onPrepareOptionsMenu quando isso é substituído e o usa nesse método. Certifique-se de que esse método seja chamado sempre que um evento ocorrer (como clique no botão) ou no segmento da interface do usuário da atividade, manipulador ou pós-execução de tarefa assíncrona.

Você deve conhecer antecipadamente o índice deste item de menu que deseja alterar. Após limpar o menu, você precisa aumentar o XML do menu e atualizar o nome ou o ícone do item.


0

Para pessoas que precisam do título definido estaticamente. Isso pode ser feito no AndroidManifest.xml

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

Texto do título do menu Opções


3
Perguntas é para dinamicamente, não estaticamente!
— EngineSense

ainda surgiu na pesquisa do Google e me ajudou, obrigado pela postagem
— bruchowski

0

Eu precisava mudar o ícone do menu para o fragmento. Alterei um pouco a resposta de Charles para essa pergunta no fragmento:

    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);
         }
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.