Скрыть/показать пункт меню опций панели действий для разных фрагментов

У меня есть активность фрагмента Шерлока, в которой есть 3 фрагмента.

Фрагмент A, Фрагмент B, Фрагмент C — это три фрагмента. Я хочу показать готовое меню опций только во фрагменте B.

И действие начинается с фрагмента A. Когда выбран фрагмент B, добавляется кнопка «Готово».

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    if(!menusInflated){
        inflater.inflate(R.menu.security, menu);
        menusInflated=true;
    }

    super.onCreateOptionsMenu(menu, inflater);
}

Когда я снова запускаю фрагмент A, я хочу выбрать меню DONE (которое было установлено во фрагменте B), для этого я делаю так

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

Но это совсем не скрывает, а также выдает исключение NullPointerException, когда действие сначала запускается с фрагментом A.

Пожалуйста, дайте мне знать, в чем проблема.


person Gaurav Arora    schedule 20.04.2014    source источник
comment
Вы решаете проблему? , У меня та же проблема. Спасибо   -  person user3383415    schedule 23.04.2014
comment
Этот вопрос не соответствует вашей проблеме. Вам не нужно скрывать кнопки из панели действий, вам нужно убедиться, что опции панели действий загружаются правильно для разных фрагментов. используйте menu.clear() перед тем, как раздувать меню в каждой функции onCreateOptionsMenu(), которая удалит из него все устаревшие параметры.   -  person C0D3LIC1OU5    schedule 12.05.2014
comment
просто чтобы уточнить, в вашем случае вам нужно переопределить onCreateOptionsMenu() с пустым меню/меню по умолчанию в вашем фрагменте A (и также использовать menu.clear()). Вам также может понадобиться сделать это для вашего фрагмента C. Убедиться, что меню ActionBar ведет себя правильно во фрагментах вручную, — это стоимость использования фрагментов для отображения содержимого вместо использования действий.   -  person C0D3LIC1OU5    schedule 12.05.2014
comment
Просто напоминание принять ответ в качестве решения, если какой-либо из приведенных ниже ответов помог вам.   -  person C0D3LIC1OU5    schedule 04.03.2015


Ответы (12)


Это один из способов сделать это:

добавить "группу" в ваше меню:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <group
        android:id="@+id/main_menu_group">
         <item android:id="@+id/done_item"
              android:title="..."
              android:icon="..."
              android:showAsAction="..."/>
    </group>
</menu>

затем добавьте

Menu menu;

переменную для вашей активности и установите ее в своем переопределении onCreateOptionsMenu:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    this.menu = menu;
    // inflate your menu here
}

После этого добавьте и используйте эту функцию в своей деятельности, когда хотите показать/скрыть меню:

public void showOverflowMenu(boolean showMenu){
    if(menu == null)
        return;
    menu.setGroupVisible(R.id.main_menu_group, showMenu);
}

Я не говорю, что это лучший/единственный способ, но он хорошо работает для меня.

person C0D3LIC1OU5    schedule 29.04.2014
comment
Я думаю, что это отличное решение! Это просто и чисто. - person Zapnologica; 13.01.2015
comment
Я не пробовал это, но приведенный ниже код Silambarasan отлично сработал для меня. - person Rizwan Sohaib; 25.08.2016
comment
Лучшее решение! Спасибо! - person Alex Evtushik; 07.10.2016
comment
у меня не работало с элементом поиска и app:actionViewClass=android.support.v7.widget.SearchView . Когда я закрываю окно поиска, происходит что-то странное. - person Alberto M; 26.10.2017

Попробуй это...

Вам не нужно снова переопределять onCreateOptionsMenu() в вашем классе Fragment. Видимость пунктов меню можно изменить, переопределив метод onPrepareOptionsMenu(), доступный в классе Fragment.

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_search).setVisible(false);
    super.onPrepareOptionsMenu(menu);
}
person Silambarasan Poonguti    schedule 01.10.2015
comment
Работает лучше всего для меня! Это должен быть принятый ответ. - person Tanuj Dhaundiyal; 04.03.2016
comment
Я пытаюсь назвать эту форму действием, производным от AppCompatActivity, и метод setHasOptionsMenu() не разрешается. - person techtinkerer; 15.10.2016
comment
@techtinkerer: вы должны переопределить эти методы во фрагменте, которые переопределяют onCreateOptionsMenu() в родительской Activity. - person Silambarasan Poonguti; 15.10.2016
comment
Мне пришлось добавить setHasOptionsMenu(true) в onViewCreated для всех тех фрагментов, которые я хотел скрыть. Есть ли способ написать setHasOptionsMenu только один раз, и значок скроется в любом фрагменте, который я переопределяю onPrepareOptionsMenu ? - person gegobyte; 22.09.2018
comment
@Chinmay Sarupria, да, ты можешь! Создайте BaseFragment и сделайте это в этом фрагменте, а затем расширьте его на свои дочерние фрагменты, которые вы хотите скрыть. - person Silambarasan Poonguti; 23.09.2018

Чтобы отображать элементы действий (кнопки действий) в ActionBar фрагментов там, где они только нужны, сделайте следующее:

Допустим, вы хотите, чтобы кнопка save отображалась только во фрагменте, где вы принимаете ввод для элементов, а не во фрагменте, где вы просматриваете список элементов, добавьте это в метод OnCreateOptionsMenu фрагмента, где вы просматриваете элементы:

public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    if (menu != null) {

        menu.findItem(R.id.action_save_item).setVisible(false);
    }
}

ПРИМЕЧАНИЕ. Чтобы это работало, вам нужен метод onCreate() в вашем фрагменте (где вы хотите скрыть кнопку элемента, фрагмент представления элемента в нашем примере) и добавьте setHasOptionsMenu(true) следующим образом:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

Возможно, это не лучший вариант, но он работает и это просто.

person Ojonugwa Jude Ochalifu    schedule 31.05.2015

Это точно сработает, я думаю...

// Declare
Menu menu;
MenuItem menuDoneItem;

// Then in your onCreateOptionMenu() method write the following...
@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        this.menu=menu;
        inflater.inflate(R.menu.secutity, menu);
            }

// In your onOptionItemSelected() method write the following...
@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.done_item:
                this.menuDoneItem=item;
                someOperation();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

// Now Making invisible any menu item...
public void menuInvisible(){
setHasOptionsMenu(true);// Take part in populating the action bar menu
            menuDoneItem=(MenuItem)menu.findItem(R.id.done_item);
                menuRefresh.setVisible(false); // make true to make the menu item visible.
}

//Use the above method whenever you need to make your menu item visible or invisiable

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

person Pravinsingh Waghela    schedule 16.01.2015

Попробуй это

@Override
public boolean onCreateOptionsMenu(Menu menu){
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.custom_actionbar, menu);
    menu.setGroupVisible(...);
}
person Petrovich Denis    schedule 25.11.2014
comment
Пожалуйста, добавьте несколько комментариев, объясняющих, как то, что вы поставили, отвечает на вопрос - ответы только на код не приветствуются. - person Ajean; 25.11.2014

Установив видимость всех элементов в меню, меню панели приложений или дополнительное меню будут автоматически скрыты.

Пример

 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);
}
person Hantash Nadeem    schedule 26.03.2018

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

 @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         if (fragment_it == 6) {
             MenuInflater inflater = getMenuInflater();
             inflater.inflate(R.menu.custom_actionbar, menu);
         }
     } 
person Ibraheem Saoud    schedule 12.06.2014
comment
Но как написать код onOptionSelected во фрагменте? - person Prachi; 21.11.2014
comment
вы должны написать это в классе Activity, а не во фрагменте, фрагмент_он укажет, какой фрагмент вы используете прямо сейчас, а затем вы раздуете соответствующее меню. - person Ibraheem Saoud; 11.02.2015

Здравствуйте, у меня есть лучшее решение для этого, предположим, вам нужно скрыть определенный элемент в методе создания меню и показать этот элемент в другом фрагменте. Я беру пример с двумя пунктами меню: один — редактировать, а другой — удалять. например меню xml, как указано ниже:

sell_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">

<item
    android:id="@+id/action_edit"
    android:icon="@drawable/ic_edit_white_shadow_24dp"
    app:showAsAction="always"
    android:title="Edit" />

<item
    android:id="@+id/action_delete"
    android:icon="@drawable/ic_delete_white_shadow_24dp"
    app:showAsAction="always"
    android:title="Delete" />

Now Override the two method in your activity & make a field variable mMenu as:

  private Menu mMenu;         //  field variable    


  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.sell_menu, menu);
    this.mMenu = menu;

    menu.findItem(R.id.action_delete).setVisible(false);
    return super.onCreateOptionsMenu(menu);
  }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.action_delete) {
       // do action
        return true;
    } else if (item.getItemId() == R.id.action_edit) {
      // do action
        return true;
    }

    return super.onOptionsItemSelected(item);
 }

Сделайте два следующих метода в своей деятельности и вызовите их из фрагмента, чтобы скрыть и показать элемент меню. Эти методы таковы:

public void showDeleteImageOption(boolean status) {
    if (menu != null) {
        menu.findItem(R.id.action_delete).setVisible(status);
    }
}

public void showEditImageOption(boolean status) {
    if (menu != null) {
        menu.findItem(R.id.action_edit).setVisible(status);
    }
}

Это Solve с моей стороны, я думаю, это объяснение поможет вам.

person Sandeep Sankla    schedule 07.09.2017

Хотя вопрос старый и ответил. На это есть более простой ответ, чем упомянутый выше. Вам не нужно использовать какие-либо другие переменные. Вы можете создавать кнопки на панели действий независимо от того, какой фрагмент вы хотите, вместо того, чтобы делать вещи видимости (показать/скрыть).

Добавьте следующее во фрагмент, если вам нужен пункт меню.

public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

Пример файла menu.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/action_addFlat"
        android:icon="@drawable/add"
        android:showAsAction="ifRoom|withText"
        android:title="@string/action_addFlat"/>
</menu>

Обработка событий onclick обычная.

person Suresh    schedule 23.04.2015
comment
Это именно то, что я сделал, но не работает для меня. При переключении на другой фрагмент (я использую ViewPager) добавленный элемент все еще виден. - person alfoks; 23.06.2015

Поздно на вечеринку, но ответы выше, похоже, не сработали для меня.

Мой первый фрагмент вкладки (использующий getChildFragmentManager() для внутренних вкладок) имеет меню для отображения значка поиска и использует android.support.v7.widget.SearchView для поиска во фрагменте внутренней вкладки, но с переходом на другие вкладки (у которых также есть внутренние вкладки). использование getChildFragmentManager()) не удалит значок поиска (поскольку не требуется) и, следовательно, по-прежнему доступен без какой-либо функции, возможно, поскольку я использую ниже (т.е. внешние основные вкладки с каждой внутренней вкладкой)

getChildFragmentManager(); 

Однако я использую приведенное ниже в своих фрагментах, содержащих/использующих getChildFragmentManager() для внутренних вкладок.

    //region onCreate
    @Override
    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setRetainInstance(true);

    //access setHasOptionsMenu()
    setHasOptionsMenu(true);

    }
    //endregion onCreate

а затем очистите пункт меню внутри onPrepareOptionsMenu для фрагментов (значок поиска и функции)

    @Override
    public void onPrepareOptionsMenu(Menu menu) {

    super.onPrepareOptionsMenu(menu);

    //clear the menu/hide the icon & disable the search access/function ...
    //this will clear the menu entirely, so rewrite/draw the menu items after if needed
    menu.clear();

    }

Работает хорошо, и при переходе обратно на вкладку / внутреннюю вкладку с функциями значка поиска снова отображается значок поиска и функции.

Надеюсь это поможет...

person BENN1TH    schedule 21.01.2018

Хорошо, я трачу пару часов, чтобы получить это решение. По-видимому, вы можете получить пункт меню с панели инструментов в любом месте действия или фрагмента. Так что в моем случае.

var menuItem = toolbar.menu;   

Теперь, чтобы получить конкретный элемент из пункта меню

favIcon = menuItem.findItem(R.id.favourite);      

Примечание: favIcon - это MenuItem, объявляющий глобальным
Теперь, если вы можете делать все, что хотите, для этого значка,
например. сделать его невидимым

favIcon?.isVisible=false
person codingwithtashi    schedule 13.03.2021

По какой-то причине метод не работал у меня, вот как я решил его в соответствии с принятым решением

//This should be in on create
new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                showOverflowMenu(false);
            }
        },100);


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



public void showOverflowMenu(boolean showMenu){
        if(menu == null)
            return;
        menu.setGroupVisible(R.id.grp, showMenu);
    }
person koshur    schedule 26.07.2021