Как скрыть пункт меню на панели действий?


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?
Разз

3
Если вы сделаете свой флаг логическим, вы можете просто установить видимость элемента на флаг (или! Флаг), если это необходимо. Итак, item.setVisbility (! Flag); делает это одним вкладышем без условия if.
jwehrle

где определяется переменная "menu"?
Джонатан

Это передается в качестве параметра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 () следует использовать для логики show / hide вместо onCreateOptionsMenu (), поскольку он вызывается только один раз, поэтому бесполезно, если вы хотите изменить пункты меню после его инициализации. Так что надуйте в onCreate, но покажите / спрячьте в onPrepare, затем используйте invalidateOptionsMenu()для обновления меню.
JCutting8

24

не работал для меня Я должен был явно использоватьonPrepareOptionsMenu чтобы установить элемент невидимым.

Так что используйте onCreateOptionsMenuдля создания меню и onPrepareOptionsMenuизменения видимости и т. Д.


1
Для меня это работало в обоих направлениях, но на основе документов Android onPrepareOptionsMenu кажется подходящим местом для выполнения этого типа операции: «Подготовьте стандартное меню параметров экрана для отображения. Это вызывается прямо перед отображением меню, каждый раз, когда оно отображается . Вы можете использовать этот метод, чтобы эффективно включать / отключать элементы или иным образом динамически изменять содержимое. "
Юваль

Да, это идеально. onPrepareOptionsMenu () следует использовать для логики show / hide вместо onCreateOptionsMenu (), так как он вызывается только один раз, поэтому бесполезно, если вы хотите изменить пункты меню после его инициализации. Так что надуйте в onCreate, но покажите / спрячьте в onPrepare, затем используйте invalidateOptionsMenu()для обновления меню.
JCutting8

9

Изначально установите видимость пункта меню в false в файле макета меню следующим образом:

<?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

Это сработало для меня как из Activity, так и из Fragment

@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 возвращает логическое значение, а не void.
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 (). Этот метод передает вам объект Menu в том виде, в котором он существует в данный момент, чтобы вы могли изменить его, например добавить, удалить или отключить элементы. (Фрагменты также обеспечивают обратный вызов onPrepareOptionsMenu ().) - Официальный сайт AndroidDeveloper -

Как рекомендуется Вы можете использовать этот метод onOptionsItemSelected (элемент MenuItem) для отслеживания пользовательских вводов.

@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

Лучший способ скрыть все элементы в меню с помощью одной команды - использовать «group» в вашем меню 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
}

Если вы хотите использовать эту команду где-либо еще в своей деятельности, не забудьте сохранить класс меню в локальном и всегда проверять, имеет ли меню значение null, потому что вы можете выполнить его до 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

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

Пункты меню связаны с такими элементами, как «Панель навигации », которые, в свою очередь, связаны с соответствующим действием.

Поэтому инициализируйте эти представления в Activity (), а затем получите доступ к пунктам меню в этих представлениях.

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 kotlin, скрыть или установить видимость пункта меню в панели действий программно.

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.