Як приховати пункт меню на панелі дій?


346

У мене є панель дій з меню. Як я можу приховати / показати цей пункт меню?

Це те, що я намагаюся зробити:

MenuItem item = (MenuItem) findViewById(R.id.addAction);
item.setVisible(false);
this.invalidateOptionsMenu();

Відповіді:


484

Отримайте MenuItemвказівку на такий елемент, зателефонуйте setVisibleна нього, щоб відрегулювати його видимість, а потім зателефонуйте invalidateOptionsMenu()на свою активність, щоб меню ActionBar було відповідно налаштоване.

Оновлення: A MenuItem- це не звичайний вигляд, який є частиною вашого макета. Це щось особливе, зовсім інше. Ваш код повертається nullдо, itemі це призводить до збоїв. Що замість цього вам потрібно зробити:

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

Ось послідовність, у якій слід зателефонувати: спочатку дзвоніть, invalidateOptionsMenu()а потім всередині onCreateOptionsMenu(Menu)отримуйте посилання на MenuItem (зателефонувавши menu.findItem()) та зателефонуйте setVisible()на нього


Це те, про що я думав спочатку, але це руйнує додаток.
Стир Золтан

3
@Stir Zoltán: Ну ось так ви це робите, можливо, ви робите це неправильно, якщо він забиває програму. Наприклад, це MenuItemможе бути nullтому, що ви використовуєте getItemзамість цього findItem. Ми ніколи не могли знати, не бачивши і ваш код, і журнал збоїв.
К-бало

Гаразд, але як я можу отримати посилання на меню поза методом onCreateOptionsMenu?
Стир Золтан

7
@Stir Zoltán: Я вважаю, що ви не маєте сенсу з цим останнім коментарем ... Просто знайдіть посилання на пункт меню onCreateOptionsMenuі встановіть видимість цього пункту в цій точці. Або тримайте посилання навколо, поки не вирішите, чи воно повинно бути видимим чи ні.
К-бал

33
Я думаю, що (у кращому випадку) ця відповідь погано сформульована, оскільки послідовність кроків неправильна. Правильна послідовність полягає в тому, щоб спочатку зателефонувати, invalidateOptionsMenu()а потім всередину onCreateOptionsMenu(Menu)отримати посилання на MenuItem(подзвонивши menu.findItem()) та зателефонувавши setVisible()на нього. Відповіді suhas_sm та P1r4nh4 представляють правильний підхід.
Тед Хопп

163

Знайдено доповнення до цього питання:

Якщо ви хочете змінити видимість елементів меню в дорозі, вам просто потрібно встановити змінну учасника у вашій діяльності, щоб пам’ятати, що ви хочете приховати меню, а також зателефонувати invalidateOptionsMenu()та приховати пункти у переоформленому onCreateOptionsMenu(...)способі.

//anywhere in your code
...
mState = HIDE_MENU; // setting state
invalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again
...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // inflate menu from xml
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.settings, menu);

    if (mState == HIDE_MENU)
    {
        for (int i = 0; i < menu.size(); i++)
            menu.getItem(i).setVisible(false);
    }
}

У своєму прикладі я приховав усі предмети.


2
Це саме те, що я шукав. тримаючись за MenuItem і викликаючи setVisible (), схоже, не робив того, чого я очікував (можливо, тому, що я викликав invalidateOptionsMenu () після цього, тим самим відновивши меню), але в будь-якому випадку - це працює саме так, як я сподівався, дякую!
Метт

4
Якщо ви збираєтесь приховати кожен предмет, є простіший спосіб. Замість того, щоб переглядати кожен елемент тут, ви можете просто зробити: if (HIDE_MENU) { return false; } else { getSupportMenuInflater().inflate(R.menu.menu_settings, menu); return true; }Документи констатують: "Ви повинні повернути значення true для відображення меню; якщо ви повернете false, воно не відображатиметься".
w3bshark

Також хочу зазначити, що такий підхід набагато чіткіший, ніж прийнята відповідь. Дякую, що поділились!
w3bshark

зателефонувавши invalidateOptionMenu () onCreateOptionMenu () викликав, і я обробляю мої умови в onCreateOptionMenu (). Дякуємо за гарну відповідь
user1912026

onPrepareOptionsMenu()слід використовувати для логіки шоу / приховування замість того, onCreateOptionsMenu()як він називається лише один раз, тому не корисний, якщо ви хочете змінити пункти меню після його ініціалізації. Тож надуйте в onCreate, але покажіть / ховайтеся в onPrepare.
JCutting8

89

Так.

  1. Ви можете встановити прапор / умову.
  2. Телефонуйте, invalidateOptionsMenu()коли хочете приховати цю опцію. Це зателефонуєonCreateOptionsMenu() .
  3. В onCreateOptionsMenu(), перевірка прапора / стану і показати або приховати його наступним чином:
MenuItem item = menu.findItem(R.id.menu_Done);

if (flag/condition)) {
  item.setVisible(false); 
} else { }

2
Чи не повинно бути invalidateOptionsMenuзамість цього invalidateOptions?
razz

3
Якщо ви зробите свій прапор булевим, ви можете просто встановити видимість елемента на прапор (або! Прапор), якщо це необхідно. Отже, item.setVisbility (! Прапор); робить це одним вкладишем без умови, якщо немає.
jwehrle

де визначена змінна "меню"?
Джонатан

Це передано як параметр доonCreateOptionsMenu
suhas_sm

використання цього методу означатиме, що предмет все-таки витрачає простір, і у вас може виникнути «прогалина» у вашому інтерфейсі, де має бути кнопка. Використання RemoveItem в onPrepareOptionsMenu () зробить свою справу.
JCutting8

39

Ви можете зателефонувати так:

MenuItem item = menu.findItem(R.id.my_item);
item.setVisible(false);

Оновлення:

Переконайтеся , що ваш код не повертається nullна itemабо він може не додатки.


використання цього методу означатиме, що предмет все-таки витрачає простір, і у вас може виникнути «прогалина» у вашому інтерфейсі, де має бути кнопка. Використання RemoveItem в onPrepareOptionsMenu () зробить свою справу.
JCutting8

33

Я шукав відповідь з трохи більше контексту. Тепер, коли я це зрозумів, я додам цю відповідь.

Приховати кнопку за замовчуванням у меню xml

За замовчуванням кнопка спільного доступу буде прихована, як встановлено android:visible="false".

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

main_menu.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">

    <!-- hide share button by default -->
    <item
        android:id="@+id/menu_action_share"
        android:icon="@drawable/ic_share_white_24dp"
        android:visible="false"     
        android:title="Share"
        app:showAsAction="always"/>

    <item
        android:id="@+id/menu_action_settings"
        android:icon="@drawable/ic_settings_white_24dp"
        android:title="Setting"
        app:showAsAction="ifRoom"/>

</menu>

Показати кнопку в коді

Але необов'язково може бути показана кнопка спільного використання на основі певної умови.

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

MainActivity.java

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    MenuItem shareItem = menu.findItem(R.id.menu_action_share);

    // show the button when some condition is true
    if (someCondition) {        
        shareItem.setVisible(true);
    }

    return true;
}

Дивись також


onPrepareOptionsMenu () повинен використовуватися для показу / приховування логіки замість onCreateOptionsMenu (), оскільки він викликається лише один раз, тому не корисний, якщо ви хочете змінити пункти меню після його ініціалізації. Тож надуйте onCreate, але покажіть / сховайте в onPrepare, а потім використовуйте invalidateOptionsMenu()для оновлення меню.
JCutting8

24

не працювало для мене. Довелося явно використовувати, onPrepareOptionsMenuщоб встановити предмет невидимим.

Тому використовуйте onCreateOptionsMenuдля створення меню та onPrepareOptionsMenuзміни видимості тощо.


1
Для мене це працювало обома способами, але на основі документів Android, onPrepareOptionsMenu схоже, потрібне місце для здійснення такого типу операцій: "Підготуйте меню до стандартних опцій екрану для відображення. Це викликається перед тим, як меню відображатиметься кожного разу, коли воно відображається Ви можете використовувати цей метод для ефективного включення / відключення елементів або іншим чином динамічно змінювати вміст. "
yuval

Так, це ідеально. onPrepareOptionsMenu () повинен використовуватися для показу / приховування логіки замість onCreateOptionsMenu (), оскільки він викликається лише один раз, тому не корисний, якщо ви хочете змінити пункти меню після його ініціалізації. Тож надуйте onCreate, але покажіть / сховайте в onPrepare, а потім використовуйте invalidateOptionsMenu()для оновлення меню.
JCutting8

9

Спочатку встановіть видимість пункту меню в помилковому файлі меню таким чином:

<?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:visible="false"
        android:id="@+id/action_do_something"
        android:title="@string/txt_do_something"
        app:showAsAction="always|withText"
        android:icon="@drawable/ic_done"/>
</menu>

Потім ви можете просто встановити видимість пункту меню в false у вашому onCreateOptionsMenu () після надуття меню.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(menu,R.menu.menu);
    MenuItem item = menu.findItem(R.id.menuItemId);
    if (item != null){
        item.setVisible(false);
    }
}

onCreateOptionsMenu не повертає булевого значення. Але рішення працювало чудово, хоча
Йосип


7

Це працювало для мене як з діяльності, так і з фрагмента

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    if (menu.findItem(R.id.action_messages) != null)
        menu.findItem(R.id.action_messages).setVisible(false);
}

1
У моєму випадку onPrepareOptionsMenu повертає булеві, а не недійсні.
CoolMind

6

Відповідь P1r4nh4 працює добре, я просто спростив її за допомогою булевого прапора:

public int mState = 0; //at the top of the code
//where you want to trigger the hide action
mState = 1; // to hide or mState = 0; to show
invalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again
...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    // inflate menu from xml
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.settings, menu);

    if (mState == 1) //1 is true, 0 is false
    {
        //hide only option 2
            menu.getItem(2).setVisible(false);
    }
}

2
Використання 0і 1не є "булевим прапором", це псевдобулевий. до того ж, тут немає жодної причини використовувати фактичну булеву форму.
Інго Бюрк

2
Крім того, у вас може бути кілька станів, не одне, щоб сховати, а одне показати. Залежно від складності вашої програми та відмови від писати нові дії для нових станів програми, у вас може бути стан SHOW_ALL, HIDE_ALL, а також стан HIDE_EDIT або HIDE_SHARE, якщо ви хочете приховати певні частини свого меню.
P1r4nh4

4

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

Після виклику системи onCreateOptionsMenu () вона зберігає екземпляр меню, яке ви заповнюєте, і не зателефонує onCreateOptionsMenu () знову, якщо меню з якихось причин не буде скасовано. Однак ви повинні використовувати onCreateOptionsMenu () лише для створення початкового стану меню та не для внесення змін протягом життєвого циклу діяльності.

Якщо ви хочете змінити меню параметрів на основі подій, що відбуваються протягом життєвого циклу діяльності, це можна зробити за допомогою методу onPrepareOptionsMenu (). Цей метод передає вам об’єкт меню, як він існує, щоб ви могли його змінити, наприклад додавати, видаляти або відключати елементи. (Фрагменти також надають зворотний виклик onPrepareOptionsMenu ().) - Офіційний сайт AndroidDeveloper -

Як рекомендовано Ви можете використовувати цей метод onOptionsItemSelected (пункт менюItem) відстежувати введення користувачів.

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    if (id == R.id.edit) {
        Intent intent = new Intent(this, ExampleActivity.class);
        intent.putExtra(BUNDLE_KEY, mConnection);
        startActivityForResult(intent, PICK_CHANGE_REQUEST);
        return true;
    } else if (id == R.id.delete) {
        showDialog(this);
        return true;
    }

    return super.onOptionsItemSelected(item);
}

Якщо вам потрібно змінити елементи меню під час виконання, ви можете використовувати onPrepareOptionsMenu (меню меню), щоб змінити їх

@Override
public boolean onPrepareOptionsMenu(Menu menu){

    if (Utils.checkNetworkStatus(ExampleActivity.this)) {
        menu.findItem(R.id.edit).setVisible(true);
        menu.findItem(R.id.delete).setVisible(true);
    }else {
        menu.findItem(R.id.edit).setVisible(false);
        menu.findItem(R.id.delete).setVisible(false);
    }
    return true;
} 

деякі елементи завжди видно, тож коли я setVisible(false)для завжди видимого елемента, він не зникає, поки не натискаю на три крапки (саме меню). Якщо я використовую invalidateOptionsMenu()в onPrepareOptionsMenuелементах, негайно реорганізую себе, але вони втрачають свої дії (якщо я натискаю на будь-який предмет, він нічого не робить).
Алітон Олівейра

3

встановити значення змінної та викликати invalidateOptionsMenu ();

наприклад

    selectedid=arg2;
            invalidateOptionsMenu();


 public boolean onPrepareOptionsMenu(Menu menu) {

    if(selectedid==1){
        menu.findItem(R.id.action_setting).setVisible(false);
        menu.findItem(R.id.action_s2).setVisible(false);
        menu.findItem(R.id.action_s3).setVisible(false);
    }
    else{
        if(selectedid==2){
            menu.findItem(R.id.action_search).setVisible(false);
            menu.findItem(R.id.action_s4).setVisible(false);
            menu.findItem(R.id.action_s5).setVisible(false);
        }
    }
    return super.onPrepareOptionsMenu(menu);
}

деякі елементи завжди видно, тож коли я setVisible(false)для завжди видимого елемента, він не зникає, поки не натискаю на три крапки (саме меню). Якщо я використовую invalidateOptionsMenu()в onPrepareOptionsMenuелементах, негайно реорганізую себе, але вони втрачають свої дії (якщо я натискаю на будь-який предмет, він нічого не робить).
Алітон Олівейра

3

Ви можете toolbar.getMenu().clear();приховати всі пункти меню одночасно


@Ajeet_Yadav Чи є спосіб зробити меню видимим після того, як ви очистите його?
Шон

3

Встановивши видимість усіх елементів у меню, меню панелі додатків або меню переповнення буде автоматично приховано

Приклад

private Menu menu_change_language;

...

...

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    ...
    ...
    menu_change_language = menu;
    menu_change_language.findItem(R.id.menu_change_language)
           .setVisible(true);

    return super.onCreateOptionsMenu(menu);
}

Перш ніж перейти до іншого фрагмента, використовуйте наступний код:

if(menu_change_language != null){                 
    menu_change_language.findItem(R.id.menu_change_language)
       .setVisible(false);
}

2

https://stackoverflow.com/a/21215280/466363 - відповіли Look Alterno та Sufian

  • ActivityCompat.invalidateOptionsMenu () не повертає виклик onPrepareOptionsMenu (); воно просто оновить меню безпосередньо.
  • Мій someMethod () викликає з декількох місць, ще до onCreateOptionsMenu (), тому я повинен перевірити mMenu! = Null.
  • має працювати за допомогою API 8

.

private Menu mMenu;
   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
       inflater.inflate(R.menu.track_fragment, menu);
       mMenu = menu;
       }
   ...
   private void someMethod() {
   ...
       if (mMenu != null) {
          MenuItem item = mMenu.findItem(R.id.new_track);
          if (item != null) {
               item.setVisible(false);
               ActivityCompat.invalidateOptionsMenu(this.getActivity());
           }
       }
   ...
   }
  • ActivityCompat.invalidateOptionsMenu () не повертає виклик onPrepareOptionsMenu (); воно просто оновить меню безпосередньо.

  • Мій someMethod () викликає з декількох місць, ще до onCreateOptionsMenu (), тому я повинен перевірити mMenu! = Null.

  • має працювати за допомогою API 8

2

Якщо ви зробили все, як описано вище, але пункт меню все ще видно, перевірте, чи посилаєтесь на унікальний ресурс. Наприклад, у onCreateOptionsMenu або onPrepareOptionsMenu

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);
    MenuItem menuOpen = menu.findItem(R.id.menu_open);
    menuOpen.setVisible(false);
}

Ctrl + Клацніть R.id.menu_open і перевірте, чи існує він лише в одному файлі меню. У випадку, коли цей ресурс уже використовується де-небудь і завантажений у активності, він спробує там заховатися.


2

Найкращий спосіб приховати всі елементи в меню лише однією командою - використовувати "групу" у своєму меню xml. Просто додайте всі пункти меню, які будуть у вашому меню переповнення всередині тієї самої групи.

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

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/someItemNotToHide1"
        android:title="ITEM"
        app:showAsAction="always" />

    <item
        android:id="@+id/someItemNotToHide2"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView|ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:title="Search"/>

    <group android:id="@+id/overFlowItemsToHide">
    <item android:id="@+id/someID" 
    android:orderInCategory="1" app:showAsAction="never" />
    <item android:id="@+id/someID2" 
    android:orderInCategory="1" app:showAsAction="never" />
    <item android:id="@+id/someID3" 
    android:orderInCategory="1" app:showAsAction="never" />
    </group>
</menu>

Потім у своїй діяльності (бажано в onCreateOptionsMenu) використовуйте команду setGroupVisible для встановлення видимості всіх пунктів меню на false або true.

public boolean onCreateOptionsMenu(Menu menu) {
   menu.setGroupVisible(R.id.overFlowItems, false); // Or true to be visible
}

Якщо ви хочете використовувати цю команду в будь-якому іншому місці у своїй діяльності, не забудьте зберегти клас меню в локальному і завжди перевіряйте, чи меню недійсне, тому що ви можете виконати перед createOptionsMenu:

Menu menu;

public boolean onCreateOptionsMenu(Menu menu) {
       this.menu = menu;

}

public void hideMenus() {
       if (menu != null) menu.setGroupVisible(R.id.overFlowItems, false); // Or true to be visible       
}


1

Я думаю, що кращим підходом було б використовувати змінну члена для меню, ініціалізувати її в onCreateOptionsMenu () і просто використовувати setVisible () згодом, не змінюючи меню параметрів.


1

цей код працював на мене

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu,menu);
    if (Application.sharedPreferences.getInt("type",1) == 2)
    {
        menuItem = menu.findItem(R.id.menu_travel_orders);
        menuItem.setVisible(false);
    }
    return super.onCreateOptionsMenu(menu);
}

1

Цей підхід працював на мене:

private  Menu thismenu;

if (condition)
{
   if(thismenu != null)
   {
       thismenu.findItem(R.id.menu_save).setVisible(true);
       Toast.makeText(ProfileActivity.this, 
    ""+thismenu.findItem(R.id.menu_save).getTitle(),
                Toast.LENGTH_SHORT).show();
   }else
   {
       thismenu.findItem(R.id.menu_save).setVisible(false);
   }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   getMenuInflater().inflate(R.menu.profile_menu, menu);
   thismenu = menu;

   return true;
}

1

Ви намагаєтеся отримати доступ до пункту меню із діяльності, яка не має доступу до області. Виклик пошуку пункту меню повернеться до нуля , оскільки представлення не пов'язане ні з активністю, ні з макетом ви дзвоните.

Пункти меню пов'язуються з такими пунктами, як "Панель навігації ", які в свою чергу пов'язуються з відповідною діяльністю.

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

Navigation navView;
navView = findViewById(R.id.navigationView);

MenuItem item = navView.getMenu().findItem(R.id.item_hosting);
item.setVisible(false);

1

використання invalidateOptionsMenu()

для того, щоб зателефонувати onPrepareOptionsMenu(menu: Menu?)

ви повинні використовувати onCreateOptionsMenu () лише для створення початкового стану меню та не для внесення змін протягом життєвого циклу діяльності ...

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

https://developer.android.com/guide/topics/ui/menus


0

Android котлін, програмно приховає або встановить видимість елемента меню на панелі дій.

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    val inflater = menuInflater
    inflater.inflate(R.menu.main_menu, menu)
    val method = menu.findItem(R.id.menu_method)
    method.isVisible = false //if want to show set true
    return super.onCreateOptionsMenu(menu)
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.