65

I have a Sherlock Fragment Activity in which there are 3 Fragments.

Fragment A, Fragment B, Fragment C are three fragments. I want to show a done option menu in Fragment B only.

And the activity is started with Fragment A. When Fragment B is selected done button is added.

@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);
}

When I again start Fragment A I want to options Menu DONE (which was set at Fragment B) for this I am doing like this

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

But this is not hiding at all, also it is giving NullPointerException when Activity if first started with Fragment A.

Please let me know what is the problem.

Marko
  • 20,385
  • 13
  • 48
  • 64
Gaurav Arora
  • 8,282
  • 21
  • 88
  • 143
  • Do you solve the problem? , I have the same problem. Thanks – user3383415 Apr 23 '14 at 15:33
  • 3
    This quesiton is not consistent with the problem you are having. You do not need to "hide" the buttons from the action bar, you need to make sure that action bar options load properly for different fragments. use menu.clear() before you inflate the menu in every onCreateOptionsMenu() function, that will remove any stale options from it. – C0D3LIC1OU5 May 12 '14 at 15:38
  • 1
    just to clarify, in your case you need to override onCreateOptionsMenu() with an empty/default menu in your Fragment A (and use menu.clear()) too. You might also need to do it for your Fragment C. Making sure the ActionBar menu is behaving properly in fragments manually is the cost of using Fragments to display the content, instead of using Activities. – C0D3LIC1OU5 May 12 '14 at 15:48
  • Just a reminder to accept an answer as a solution if any of the answers below helped you. – C0D3LIC1OU5 Mar 04 '15 at 16:23

13 Answers13

115

Try this...

You don't need to override onCreateOptionsMenu() in your Fragment class again. Menu items visibility can be changed by overriding onPrepareOptionsMenu() method available in Fragment class.

 @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);
}
Silambarasan Poonguti
  • 9,386
  • 4
  • 45
  • 38
  • 1
    Works the best for me! This should be the accepted answer. – Tanuj Dhaundiyal Mar 04 '16 at 08:00
  • I am trying to call this form an activity derived from AppCompatActivity and the method setHasOptionsMenu() doesn't resolve. – techtinkerer Oct 15 '16 at 00:01
  • @ techtinkerer: You should override these methods in fragmant which override onCreateOptionsMenu() in parent Activity. – Silambarasan Poonguti Oct 15 '16 at 05:26
  • 1
    I had to add `setHasOptionsMenu(true)` in `onViewCreated` on all those fragments I wanted to hide the icon. Is there any way I can write `setHasOptionsMenu` only once and icon hides on whichever fragment I override `onPrepareOptionsMenu` ? – gegobyte Sep 22 '18 at 18:17
  • @Chinmay Sarupria, Yes you can! Create a BaseFragment and do this stuff in that fragment then extend it on your child fragments which you want to hide. – Silambarasan Poonguti Sep 23 '18 at 05:55
77

This is one way of doing this:

add a "group" to your menu:

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

then, add a

Menu menu;

variable to your activity and set it in your override of onCreateOptionsMenu:

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

After, add and use this function to your activity when you'd like to show/hide the menu:

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

I am not saying this is the best/only way, but it works well for me.

Marko
  • 20,385
  • 13
  • 48
  • 64
C0D3LIC1OU5
  • 8,600
  • 2
  • 37
  • 47
23

To show action items (action buttons) in the ActionBar of fragments where they are only needed, do this:

Lets say you want the save button to only show in the fragment where you accept input for items and not in the Fragment where you view a list of items, add this to the OnCreateOptionsMenu method of the Fragment where you view the items:

public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    if (menu != null) {

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

NOTE: For this to work, you need the onCreate() method in your Fragment (where you want to hide item button, the item view fragment in our example) and add setHasOptionsMenu(true) like this:

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

Might not be the best option, but it works and it's simple.

Ojonugwa Jude Ochalifu
  • 26,627
  • 26
  • 120
  • 132
6

This will work for sure I guess...

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

You can also refer this link for more details, it is a very useful one.

Pravinsingh Waghela
  • 2,516
  • 4
  • 32
  • 50
5
MenuItem Import = menu.findItem(R.id.Import);
  Import.setVisible(false)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Dhina k
  • 1,481
  • 18
  • 24
4

Try this

@Override
public boolean onCreateOptionsMenu(Menu menu){
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.custom_actionbar, menu);
    menu.setGroupVisible(...);
}
ItamarG3
  • 4,092
  • 6
  • 31
  • 44
  • 2
    Please add some comments explaining how what you have put answers the question - code-only answers are discouraged. – Ajean Nov 25 '14 at 16:17
3

By setting the Visibility of all items in Menu, the appbar menu or overflow menu will be Hide automatically

Example

 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);
}

Before going to other fragment use bellow code:

if(menu_change_language != null){                 
 menu_change_language.findItem(R.id.menu_change_language)
  .setVisible(false);
}
Hantash Nadeem
  • 458
  • 6
  • 10
2

Hello I got the best solution of this, suppose if u have to hide a particular item at on create Menu method and show that item in other fragment. I am taking an example of two menu item one is edit and other is delete. e.g menu xml is as given below:

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);
 }

Make two following method in your Activity & call them from fragment to hide and show your menu item. These method are as:

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);
    }
}

That's Solve from my side,I think this explanation will help you.

Sandeep Sankla
  • 1,250
  • 12
  • 21
1

You can make a menu for each fragment, and a global variable that mark which fragment is in use now. and check the value of the variable in onCreateOptionsMenu and inflate the correct menu

 @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         if (fragment_it == 6) {
             MenuInflater inflater = getMenuInflater();
             inflater.inflate(R.menu.custom_actionbar, menu);
         }
     } 
Ibraheem Saoud
  • 153
  • 1
  • 6
  • But how to write the code of onOptionSelected in the fragment? – Prachi Nov 21 '14 at 12:15
  • you should write it in the Activity's class not the fragment's the fragment_it will indicate which fragment you are using right now and then you inflate the corresponding menu – Ibraheem Saoud Feb 11 '15 at 10:29
1

Okay I spend couple of hour to get this solution.apparently you can get menuitem from your toolbar to anywhere in activity or fragment. So in my case.

var menuItem = toolbar.menu;   

Now to get specfic item from menu item

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

Note: favIcon is MenuItem declare global
Now if you can do whatever you want to do for this icon
eg. to make it invisible

favIcon?.isVisible=false
Kunchok Tashi
  • 2,413
  • 1
  • 22
  • 30
0

Even though the question is old and answered. There is a simpler answer to that than the above mentioned. You don't need to use any other variables. You can create the buttons on action bar whatever the fragment you want, instead of doing the visibility stuff(show/hide).

Add the following in the fragment whatever u need the menu item.

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

Sample menu.xml file:

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

Handling onclick events is as usual.

Suresh
  • 1
  • 1
    This is exactly what I've done , but does not work for me. When switching to another fragment (I'm using a ViewPager), the added item is still visible. – alfoks Jun 23 '15 at 08:03
0

Late to the party but the answers above didn't seem to work for me.

My first tab fragment (uses getChildFragmentManager() for inner tabs) has the menu to show a search icon and uses android.support.v7.widget.SearchView to search within the inner tab fragment but navigating to other tabs (which also have inner tabs using getChildFragmentManager()) would not remove the search icon (as not required) and therefore still accessible with no function, maybe as I am using the below (ie outer main tabs with each inner tabs)

getChildFragmentManager(); 

However I use the below in my fragments containing/using the getChildFragmentManager() for inner tabs.

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

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

    //access setHasOptionsMenu()
    setHasOptionsMenu(true);

    }
    //endregion onCreate

and then clear the menu item inside onPrepareOptionsMenu for fragments(search icon & functions)

    @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();

    }

Works well and navigating back to the tab/inner tab with the search icon functions re displays the search icon & functions.

Hope this helps...

BENN1TH
  • 2,003
  • 2
  • 31
  • 42
0

For some reason the method was not working for me this is how I solved it according to the accepted solution

//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);
    }
koshur
  • 124
  • 1
  • 9