Android: Як увімкнути / вимкнути пункт меню опції при натисканні кнопки?


127

Я легко можу це зробити, коли використовую onCreateOptionsMenuабо onOptionsItemSelectedметоди.

Але у мене є кнопка десь на екрані, і при натисканні на цю кнопку вона повинна вмикати / вимикати пункти контекстного меню.

Відповіді:


272

У всякому разі, документація охоплює всі речі.

Зміна елементів меню під час виконання

Після створення активності onCreateOptionsMenu()метод викликається лише один раз, як описано вище. Система зберігає та повторно використовує визначені Menuвами в цьому методі, поки ваша діяльність не буде знищена. Якщо ви хочете змінити меню "Параметри" будь-коли після його створення, вам слід перекрити onPrepareOptionsMenu()метод. Це передає вам об'єкт меню таким, який він існує. Це корисно, якщо ви хочете видалити, додати, відключити або включити пункти меню залежно від поточного стану вашої програми.

Напр

@Override
public boolean onPrepareOptionsMenu (Menu menu) {
    if (isFinalized) {
        menu.getItem(1).setEnabled(false);
        // You can also use something like:
        // menu.findItem(R.id.example_foobar).setEnabled(false);
    }
    return true;
}

На Android 3.0 і новіших версіях меню параметрів вважається завжди відкритим, коли пункти меню представлені на панелі дій. Коли відбувається подія і ви хочете виконати оновлення меню, вам потрібно зателефонувати, invalidateOptionsMenu()щоб подати запит на системний виклик onPrepareOptionsMenu().


2
setEnable()чи змінюється те, що відбувається при натисканні цього меню, але не змінюється, як воно виглядає (що не так, розробники Android?). Тому чіткіше або відключити і змінити заголовок, або бажано просто зробити MenuItemневидимим.
Влад

19
Швидкий рада: поверніться, falseщоб повністю відключити меню.
Барт Фрідеріхс

5
Плюс коментар API onPrepareOptionsMenu чітко зазначає: Класи виведення повинні завжди (!) Переходити до реалізації базового класу. Ви забули там свій супер дзвінок.
AgentKnopf


Звідки ви знаєте цілий ідентифікатор MenuItem, доданий під час виконання? Ви можете додати їх лише по імені.
Антоніо Сесто

66

Для всіх версій для Android найпростіший спосіб: скористайтеся цим, щоб ПОКАЗНАТИ значок дії меню як відключений І зробити його FUNCTION також відключеним:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {

    MenuItem item = menu.findItem(R.id.menu_my_item);

    if (myItemShouldBeEnabled) {
        item.setEnabled(true);
        item.getIcon().setAlpha(255);
    } else {
        // disabled
        item.setEnabled(false);
        item.getIcon().setAlpha(130);
    }
}

1
Навіщо встановлювати альфа 0, коли видимість можна встановити на false?
MLProgrammer-CiM

8
Я не встановлюю альфа на 0, а на 130.
Френк

8
Залежить від контексту кнопки. Якщо функція, яку зазвичай використовувала кнопка, є абсолютно непридатною в поточному стані, то так, видимість повинна бути невидимою / зникла. Однак якщо ця функція звичайно може використовуватись з будь-яких причин (наприклад, якщо користувач стає членом преміум-класу, якщо користувач входить у систему, якщо користувач підключається до Інтернету і т. Д.), То приємно мати його сірим кольором тому що тоді це дозволяє користувачеві знати, що існує якась існуюча функція, до якої з якоїсь причини вони не мають доступу.
yiati

6
Налаштування піктограми невидимим не краще майже у всіх випадках використання. У випадку, якщо у вас є група, краще вони залишаються на своїх позиціях, а сірі вказують користувачеві, що є можливість, яку можна включити в певному програмному стані. зробити річ невидимою і невидимою і, ймовірно, спричинити зміни компонування дуже нерозумно. Існує причина, що більшість меню затьмарюють елементи, а не видаляють їх залежно від режиму.
RichieHH

1
Як, якщо меню не містить піктограми? Ви не можете встановитиAlpha ().
Latief Anwar

42

Ви можете зберегти елемент як змінну при створенні меню опцій, а потім змінити його властивості за бажанням.

private MenuItem securedConnection;
private MenuItem insecuredConnection;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.connect_menu, menu);
    securedConnection = menu.getItem(0);
    insecuredConnection =  menu.getItem(1);
    return true;
}

public void foo(){
       securedConnection.setEnabled(true);
}    

Це правильна відповідь на будь-яку версію Android. Затверджена відповідь дійсна лише для пристроїв API 11>.
Marco HC

2
Я спробував це, і це не працює. Ви мали на увазі onPrepareOptionsMenu?
Крістофер Пікслі

6

спростити версію @Vikas

@Override
public boolean onPrepareOptionsMenu (Menu menu) {

    menu.findItem(R.id.example_foobar).setEnabled(isFinalized);
    return true;
}

4

Як оновити поточне меню, щоб увімкнути або вимкнути елементи, коли виконано AsyncTask.

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

Це заважало додатку дозволяти користувачам натискати на пункти меню під час завантаження даних.

По-перше, я оголошу змінну стану, якщо змінна 0, відображається меню, якщо ця змінна - 1, меню приховано.

private mMenuState = 1; //I initialize it on 1 since I need all elements to be hidden when my activity starts loading.

Тоді в моєму onCreateOptionsMenu()я перевіряю цю змінну, якщо це 1, я відключаю всі свої елементи, якщо ні, я просто показую їх усі

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.menu_galeria_pictos, menu);

        if(mMenuState==1){
            for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setVisible(false);
            }
        }else{
             for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setVisible(true);
            }
        }

        return super.onCreateOptionsMenu(menu);
    }

Тепер, коли починається "Моя активність", onCreateOptionsMenu()буде називатися лише один раз, і всі мої елементи будуть втрачені, тому що я створив стан для них на початку.

Тоді я створюю AsyncTask Де я встановив цю змінну стану на 0 у своєму onPostExecute()

Цей крок дуже важливий!

Коли ви invalidateOptionsMenu();його зателефонуєте, він відновитьсяonCreateOptionsMenu();

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

 public class LoadMyGroups extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mMenuState = 1; //you can set here the state of the menu too if you dont want to initialize it at global declaration. 

        }

        @Override
        protected Void doInBackground(Void... voids) {
           //Background work

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            mMenuState=0; //We change the state and relaunch onCreateOptionsMenu
            invalidateOptionsMenu(); //Relaunch onCreateOptionsMenu

        }
    }

Результати

введіть тут опис зображення


2

найкраще рішення, коли ви працюєте на навігаційному ящику

@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.setGroupVisible(0,false);
        return true;
    }

Це приховує все меню і унеможливлює його відкриття знову
MrStahlfelge

2

Більш сучасна відповідь на старе питання:

MainActivity.kt

private var myMenuIconEnabled by Delegates.observable(true) { _, old, new ->
    if (new != old) invalidateOptionsMenu()
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    findViewById<Button>(R.id.my_button).setOnClickListener { myMenuIconEnabled = false }
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_main_activity, menu)
    return super.onCreateOptionsMenu(menu)
}

override fun onPrepareOptionsMenu(menu: Menu): Boolean {
    menu.findItem(R.id.action_my_action).isEnabled = myMenuIconEnabled
    return super.onPrepareOptionsMenu(menu)
}

menu_main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/action_my_action"
    android:icon="@drawable/ic_my_icon_24dp"
    app:iconTint="@drawable/menu_item_icon_selector"
    android:title="My title"
    app:showAsAction="always" />
</menu>

menu_item_icon_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?enabledMenuIconColor" android:state_enabled="true" />
<item android:color="?disabledMenuIconColor" />

attrs.xml

<resources>   
    <attr name="enabledMenuIconColor" format="reference|color"/>
    <attr name="disabledMenuIconColor" format="reference|color"/>
</resources>

styles.xml or themes.xml

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="disabledMenuIconColor">@color/white_30_alpha</item>
    <item name="enabledMenuIconColor">@android:color/white</item>

Прекрасний підхід, який можна використовувати без особливих котлоагрегатів по всьому додатку.
Артур

Яка у вас проблема?
ExpensiveBelly

@ExpensiveBelly сама по собі не проблема, просто публічне повідомлення.
Big McLargeHuge

1
  @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

                case R.id.item_id:

                       //Your Code....

                        item.setEnabled(false);
                        break;
              }
            return super.onOptionsItemSelected(item);
     }

З перегляду: Привіт, будь ласка, не відповідайте лише вихідним кодом. Спробуйте надати приємний опис про те, як працює ваше рішення. Дивіться: Як написати гарну відповідь? . Спасибі
sɐunıɔ ןɐ qɐp

1

Що я зробив, це зберегти посилання на Меню на onCreateOptionsMenu. Це схоже на відповідь nir, за винятком того, що замість того, щоб зберегти кожен окремий пункт, я зберегла все меню.

Оголосити меню Menu toolbarMenu;.

Потім onCreateOptionsMenuзбережіть меню до змінної

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

Тепер ви можете отримати доступ до свого меню та всіх його пунктів у будь-який час. toolbarMenu.getItem(0).setEnabled(false);


0
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    // getMenuInflater().inflate(R.menu.home, menu);
    return false;
}

2
Хоча цей код може відповісти на питання ОП, декілька пояснень допоможуть нинішнім та майбутнім користувачам зрозуміти вашу відповідь ще краще.
Том

0

Якщо видиме меню

menu.findItem(R.id.id_name).setVisible(true);

Якщо сховати меню

menu.findItem(R.id.id_name).setVisible(false);

-4

Зазвичай можна змінити властивості ваших поглядів під час виконання:

(Button) item = (Button) findViewById(R.id.idBut);

і потім...

item.setVisibility(false)

але

якщо ви хочете змінити видимість параметрів із ContextMenu, натиснувши кнопку, ви можете активувати прапор, а потім у onCreateContextMenu ви можете зробити щось подібне:

 @Override
        public void onCreateContextMenu(ContextMenu menu, 
                View v,ContextMenu.ContextMenuInfo menuInfo) {

            super.onCreateContextMenu(menu, v, menuInfo);

                menu.setHeaderTitle(R.string.context_title);

                if (flagIsOn()) {
                    addMenuItem(menu, "Option available", true);
                } else {
                    Toast.makeText(this, "Option not available", 500).show();
                }

        }

Я сподіваюся, що це допомагає


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

моя відповідь завершена. Цей код він працює, я використовував у своїх проектах
Ерік

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

onCreateContextMenuбуде викликано лише один раз, але я можу натискати кнопку багато часу, щоб увімкнути / вимкнути пункт меню.
Вікас

Так, але контекстне меню зазвичай робиться прихованим. Якщо ви натиснете «десь кнопку» і встановите прапор, як я вже сказав, це контекстне меню не буде видимим, і наступного разу, коли ви перезавантажите своє контекстне меню, ця опція буде невидимою. Інший варіант - це зробити інший тип меню з тим самим виглядом, щоб обробляти події іншими методами.
Ерік
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.