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.

Garbit
fonte
stackoverflow.com/a/32072318/1651286 deve ser a resposta aceita
Dad Akhil

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

Todd DeLand
fonte
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.

Charles Harley
fonte
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");
Pranav Raut
fonte
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;
    }
Jack
fonte
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

JxDarkAngel
fonte
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");
Oumar
fonte
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.

hyperCoder
fonte
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.

Abhinav Saxena
fonte
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

moberme
fonte
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);
         }
    }
Almaz Vildanov
fonte