Як динамічно змінювати текст пункту меню в 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 має бути прийнятою відповіддю
Ахіл Папа

Відповіді:


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


Найкраще рішення. Тому що цей метод заміни андроїд замість винаходити колесо.
Azlan Jamal

Зауважте лише, що onPrepareOptionsMenu()система Android досить часто викликається, наприклад, під час відображення діяльності та кожного разу, коли меню відображається. Тож це може бути не дуже ефективно, якщо ваше меню змінюється не дуже часто.
Mr-IDE

1
invalidateOptionsMenu()також подзвонить onCreateOptionsMenu(), тож ви можете ввести логіку оновлення onCreateOptionsMenu().
Містер-ІДЕ

Якщо ви відредагуєте це, що стосується питання, я
позначу

@Garbit оновлено для використання вашого коду з оригінального питання!
Тодд

375

Я б запропонував зберегти посилання в межах діяльності на об'єкт меню, який ви отримуєте в 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 () - з будь-якого методу, в будь-якому місці та в будь-який час).
Джек

Хоча цей підхід працює, його не рекомендується, оскільки об'єкт меню, який керує меню, не буде знати, коли змінено заголовок, і тому він не може виконувати завдання, які можуть знадобитися, коли заголовок змінюється, наприклад, макет і розрив рядків .
Чарльз Харлі

3

Краще скористайтеся переопределенням наPrepareOptionsMenu

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, коли це буде переопрацьовано і не використовується в цьому вашому методі. Будьте впевнені, що цей метод викликається щоразу, коли трапляється подія (наприклад, натискання кнопки) або в потоці UI, обробці або асинхронній задачі після виконання.

Ви повинні заздалегідь знати індекс цього пункту меню, який ви хочете змінити. Після очищення меню потрібно надути XML меню та оновити ім'я або піктограму елемента.


0

Для людей, яким потрібна назва, встановлено статично. Це можна зробити в AndroidManifest.xml

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

Параметри Текст заголовка меню


3
Питання - це динамічно, а не статично!
EngineSense

все-таки прийшов у пошук в Google і допоміг мені, дякую за публікацію
bruchowski

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.