Як оновити пункт меню, показаний на панелі ActionBar?


93

У мене активність, яка має 2 фрагменти. Обидва є ListFragments і обидва вносять MenuItems у меню. У мене є один MenuItem, який я встановив атрибут android: showAsAction, щоб він відображався як кнопка на ActionBar. Що чудово працює.

Тепер MenuItem залежить від стану. Це параметр меню Пауза / Відновлення для призупинення та відновлення черги. Моя проблема полягає в тому, що я не можу зрозуміти, як встановити початкову статую при створенні Фрагменту.

Її стан залежить від того, зупинена чи ні черга. Отже, у мене є AsyncTask, який отримує чергу і встановлює булеву (призупинену) грунтуючись на стані черги. Я закликаю onPrepareOptionsMenu, щоб встановити текст для пункту меню "Пауза" на основі останнього відомого стану черги, і це чудово працює, якщо залишити MenuItem у фактичному меню. Ви натискаєте піктограму меню, і onPrepareOptionsMenu запускається, а меню оновлюється до його відображення.

Проблема полягає в тому, що якщо я поставив той самий MenuItem на ActionBar (showAsAction), як я можу змусити його оновлюватись, не вимагаючи викликати onPrepareOptionsMenu? Мені потрібно це зробити, тому що при першому запуску програми я надсилаю запит на отримання черги, але завдання повертається після налаштування та відображення програми ActionBar. Я створив оброблювач у своєму фрагменті, який викликає кожен раз, коли я отримую оновлення черги, але звідти, як я можу оновити текст для свого MenuItem на ActionBar? Я, здається, не можу знайти спосіб встановити на даний момент меню для маніпулювання ним, за винятком onPrepareOptionMenu.

Роб В.

Відповіді:


174

Варіант №1: Спробуйте invalidateOptionsMenu(). Не знаю, чи змусить це негайно перемалювати панель дій чи ні.

Варіант №2: Дізнайтеся, чи getActionView()повертається щось для постраждалих MenuItem. Можливо, що showAsActionпросто автоматично створює для вас перегляди дій. Якщо це так, ви, мабуть, можете це ввімкнути / вимкнути View.

Я, здається, не можу знайти спосіб встановити на даний момент меню для маніпулювання ним, за винятком onPrepareOptionMenu.

Ви можете повісити на Menuпредмет, який вам передали onCreateOptionsMenu(). Цитування документів :

Ви можете сміливо триматися за меню (і за будь-якими створеними з нього елементами), вносячи зміни до нього за бажанням, до наступного виклику onCreateOptionsMenu ().


2
Спробував варіант №1, і це зробило трюк. Оскільки я намагався оновити інтерфейс користувача у зворотному дзвінку з окремого потоку, це було винятком, оскільки я фактично не був на потоці інтерфейсу. Щоб виправити це, я створив обробник і надіслав повідомлення про оновлення оброблювачу, коли був викликаний мій зворотній дзвінок. Але в кінцевому рахунку я використав getActivity (). InvalidateOptionsMenu () для оновлення меню.
брокколі

@brockoli: Ах, добре! Беручи до уваги формулювання Javadocs для цього методу, я скептично ставився до того, що це матиме бажаний ефект, хоча, здається, саме з цієї причини вони додали його до API 11 рівня. Радий почути, що це працює на тебе!
CommonsWare

Я б’юся головою об стіну, намагаючись це зрозуміти, і це працює як шарм!
MinceMan

7
Якщо ви використовуєте бібліотеку підтримки, використовуйте supportInvalidateOptionsMenu()натомість
Тім Кіст

2
@TimKist, supportInvalidateOptionsMenu()зараз застаріло; ви можете сміливо використовувати invalidateOptionsMenu().
Primož Kralj

12

в моєму випадку: invalidateOptionsMenuпросто перевстановив текст до оригінального, але безпосередньо перейшовши до пункту меню та перезаписавши текст бажання працював без проблем:

if (mnuTopMenuActionBar_ != null) {
    MenuItem mnuPageIndex = mnuTopMenuActionBar_
        .findItem(R.id.menu_magazin_pageOfPage_text);

    if (mnuPageIndex != null) {
        if (getScreenOrientation() == 1) {
            mnuPageIndex.setTitle((i + 1) + " von " + pages);
        }
        else {
            mnuPageIndex.setTitle(
                (i + 1) + " + " + (i + 2) + " " + " von " + pages);
        }
        // invalidateOptionsMenu();
    }
}

завдяки коментарю нижче, я зміг отримати доступ до пункту меню за допомогою наступного коду:

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

Як ви зрозуміли подання ActionBar mnuTopMenuActionBar_?
Пол Меннега

1
коли панель дій стає ініціалізованою, я зберігаю подання до змінної-члена ... наприклад: @Override public boolean onCreateOptionsMenu (меню меню) {MenuInflater inflater = getMenuInflater (); inflater.inflate (R.menu.magazine_swipe_activity, меню); mnuTopMenuActionBar_ = меню; повернути істинно; }
cV2

Роблячи це, у вас можуть виникнути проблеми синхронізації? Я маю на увазі. ви точно не знаєте, коли onCreateOptionMenu збирається запустити, тож ви можете дійти до свого коду з mnuTopMenuActionBar_неініціалізованим, правда? Як би ти обійшов це?
acrespo

агов, якщо ActionBar використовується (так, тут є) цей метод завжди викликається, так що немає ніяких проблем з цим ... (безпосередньо на початку діяльності) stackoverflow.com/questions/7705927 / ...
CV2

11

Щоб оновити меню з фрагмента, просто зателефонуйте:

getActivity().invalidateOptionsMenu();

4

Я використав цей код:

public boolean onPrepareOptionsMenu (Menu menu) {       
    MenuInflater inflater = getMenuInflater();
    TextView title  = (TextView) findViewById(R.id.title);
    menu.getItem(0).setTitle(
        getString(R.string.payFor) + " " + title.getText().toString());
    menu.getItem(1).setTitle(getString(R.string.payFor) + "...");
    return true;        
}

І працюючи як шарм для мене, ви можете знайти OnPrepareOptionsMenu тут


4
Для чого тут призначений MenuInflater?
ІгорГанапольський

Це чудово
Стів Камау

2

Спочатку дотримуйтесь двох рядків кодів, щоб оновити елементи рядка дій, перш ніж вам слід встановити умову в oncreateOptionMenu (). Наприклад:

Boolean mISQuizItemSelected = false;

/**
 * Called to inflate the action bar menus
 *
 * @param menu
 *      the menu
 *
 * @return true, if successful
 */

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    // Inflate the menu items for use in the action bar

    inflater.inflate(R.menu.menu_demo, menu);

    //condition to hide the menus
    if (mISQuizItemSelected) {
        for (int i = 0; i < menu.size(); i++) {
            menu.getItem(i).setVisible(false);
        }
    }

    return super.onCreateOptionsMenu(menu);
}

/**
 * Called when the item on the action bar being selected.
 *
 * @param item
 *      menuitem being selected
 *
 * @return true if the menuitem id being selected is matched
 * false if none of the menuitems id are matched
 */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getId() == R.id.action_quiz) {
        //to navigate based on the usertype either learner or leo
        mISQuizItemSelected = true;

        ActionBar actionBar = getActionBar();
        invalidateOptionMenu();
    }
}

1

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

private MenuItem menuItem_;

@Override
public boolean onCreateOptionsMenu(Menu menuF) 
{
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_layout, menuF);
    menuItem_ = menuF.findItem(R.id.menu_item_identifier);
    return true;
}

У цьому випадку ви переходите на посилання MenuItem на початку, а потім змінюєте його стан (наприклад, для зміни значків) у наступний момент часу.


-1

У Kotlin 1.2 просто зателефонуйте:

invalidateOptionsMenu()

і onCreateOptionsMenuфункція буде викликана знову.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.