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.