Как динамически изменять текст пункта меню в Android


212

Я пытаюсь изменить заголовок пункта меню вне onOptionsItemSelected(MenuItem item)метода.

Я уже делаю следующее;

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

однако я хотел бы иметь возможность изменять заголовок определенного пункта меню вне этого метода.


stackoverflow.com/a/32072318/1651286 должен быть принятым ответом
Akhil Dad

Ответы:


127

Как предложил JxDarkAngel, вызывая это из любой точки вашей активности ,

invalidateOptionsMenu();

а затем переопределить:

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

это гораздо лучший выбор. Я использовал ответ от https://stackoverflow.com/a/17496503/568197


Лучшее решение. Потому что этот метод переопределить Android, а не изобретать велосипед.
Азлан Джамал

Просто обратите внимание, что onPrepareOptionsMenu()Android-платформа вызывается довольно часто, например, при отображении действия и каждый раз, когда отображается меню. Так что это может быть не очень эффективно, если ваше меню меняется не очень часто.
Mr-IDE

1
invalidateOptionsMenu()также будет вызывать onCreateOptionsMenu(), чтобы вы могли вставить логику обновления onCreateOptionsMenu().
Mr-IDE

Если вы отредактируете это, чтобы оно соответствовало вопросу, я
Garbit

@Garbit обновлен, чтобы использовать ваш код из оригинального вопроса!
Тодд

375

Я бы предложил сохранить ссылку в действии на объект Menu, который вы получаете в onCreateOptionsMenu, а затем использовать его для извлечения элемента MenuItem, который требует изменения по мере необходимости. Например, вы можете сделать что-то вроде следующего:

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

}

Кроме того, вы можете переопределить onPrepareOptionsMenu, чтобы обновлять пункты меню каждый раз, когда оно отображается.


1
Я всегда ожидаю, что у Android будет более изящное решение подобных проблем. Кажется, самые простые ответы часто самые лучшие - спасибо.
Стивен Вулф

12

Вы можете сделать это, создать глобальный объект «Меню», а затем назначить его в onCreateOptionMenu

public class ExampleActivity extends AppCompatActivity
    Menu menu;

затем назначьте здесь

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

Затем используйте назначенный объект Меню для получения необходимых предметов.

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

5

Создайте метод setOptionsTitle () и установите поле в своем классе. Такие как:

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

...

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

}

Теперь, когда меню заполнено, измените заголовок на ваш статус:

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

        menu.add(bedStatus);


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

Мне нужно иметь возможность установить его после того, как действие было выполнено. Таким образом, поэтому не внутри этих двух методов
Гарбит

Вызовите setOptionsTitle в любой момент после того, как ваша активность будет отображена. Я думаю, я не понимаю, что вы хотите, потому что «мне нужно иметь возможность установить его после того, как действие было выполнено» означает для меня после того, как вы вызовете setContent (R.layout.id), вам может потребоваться изменить какие параметры отображается меню (что вы можете сделать с помощью setOptionsTitle () - из любого метода, в любом месте, в любое время).
Джек

Хотя этот подход работает, его не рекомендуется, поскольку объект Menu, управляющий меню, не будет знать, когда изменился заголовок, и поэтому не сможет выполнять задачи, которые могут потребоваться при изменении заголовка, например, разметка и разрывы строк. ,
Чарльз Харли

3

Вам лучше использовать переопределение 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");
   }

Вот пример


Действительно, используйте намеченный подход. :) Если вы решите сохранить локальную ссылку на меню, вам придется беспокоиться об утечках контекста, я думаю. А может и нет. Но, конечно, не с таким подходом.
Уильям Т. Маллард

3

Я использую этот код для оценки моего нижнего элемента навигации

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

2

Объявите свое поле меню.

private Menu menu;

Ниже приведен метод 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);
}

Следующим будет ваше имя сеттер деятельности. Либо нажатием кнопки, либо условным кодом

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

Это сработало для меня.


0

Мне кажется, что вы хотите изменить содержимое меню внутри локального метода, и этот метод вызывается в любое время, когда происходит событие или в потоке пользовательского интерфейса активности.

Почему бы вам не взять экземпляр Menu в глобальной переменной в onPrepareOptionsMenu, когда это переопределено, и использовать в этом вашем методе. Убедитесь, что этот метод вызывается всякий раз, когда происходит событие (например, нажатие кнопки), или в потоке пользовательского интерфейса, обработчике или асинхронной задаче после выполнения.

Вы должны заранее знать индекс этого пункта меню, который вы хотите изменить. После очистки меню вам нужно накачать меню XML и обновить имя или значок вашего элемента.


0

Для людей, которым нужен заголовок установлен статически. Это можно сделать в AndroidManifest.xml

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

Меню опций Текст заголовка


3
Вопросы для динамически, а не статично!
EngineSense

все еще
нашел в

0

Мне нужно было изменить значок меню для фрагмента. Я немного изменил ответ Чарльза на этот вопрос для фрагмента:

    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);
         }
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.