51

I got pretty helpful hints to my last questions, I hope it won't be different this time :) First, let me explain the situation. I have an activity with 2 fragments. For each fragment I have a xml menu layout, the first has four menu entries, the second one has only one. Now at first the fragment with the four menu entries is loaded. In its onCreate method I set

this.setHasOptionsMenu(true);

the onCreateOptionsMenu method

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

The xml file looks like this :

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_refresh"
      android:icon="@drawable/ic_action_search"
      android:title="Refresh"
      android:visible="true"
      android:showAsAction="ifRoom|withText" />
<item android:id="@+id/menu_clearall"
      android:icon="@drawable/ic_action_search"
      android:title="Clear"
      android:visible="true"
      android:showAsAction="ifRoom|withText" />
<item android:id="@+id/menu_addcontent"
      android:icon="@drawable/ic_action_search"
      android:title="Add Content"
      android:visible="true"
      android:showAsAction="ifRoom|withText" />
<item android:id="@+id/menu_newlist"
      android:icon="@drawable/ic_action_search"
      android:title="New List"
      android:visible="true"
      android:showAsAction="ifRoom|withText" />    
</menu>

This works fine. All menu items are there, I can click them and respond. Now when I click on the "Add Content" menu, the other fragment is loaded. There I as well set

this.setHasOptionsMenu(true);

the onCreateOptionsMenu method

@Override 
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
    Log.i("FragCreateList","onCreateOptionsMenu called");
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.menu_fragcreatelist, menu);
}

The xml file

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_editdone"
      android:icon="@drawable/ic_action_search"
      android:title="Edit Done"
      android:visible="true"
      android:showAsAction="ifRoom|withText" />         
</menu>

But in the new fragment I can't see any menu items. Neither in the action bar, nor when I press the hardware menu button. In the former fragment, two menu items were in the actionbar, the remaining two appeared when the hardware button was pressed. But here nothing is shown. I get the logcat message that the onCreateOptionsMenu method got called, but nothing happens. (I even get a call to my (empty) onPrepareOptionsMenu method, which should be called right before the menu is shown, still nothing) Any clue what could be wrong? Calling invalidateOptionsMenu doesn't do a thing. Besides, I don't know for sure which one to call, as there is a getActivity().invalidateOptionsMenu and a getFragmentManager().invalidateOptionsMenu... Thanks in advance.

Edit :

<uses-sdk
    android:minSdkVersion="14"
    android:targetSdkVersion="15" />
El Duderino
  • 855
  • 1
  • 10
  • 21
  • From the answers, it seems like this can be caused by a lot of things. I had this issue because I was using a FragmentActivity instead of an AppCompatActivity, and it worked as soon as I changed that – TallChuck Dec 04 '17 at 19:41

16 Answers16

94

I added setHasOptionsMenu(true) in onCreateView and it works fine

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    return inflater.inflate(R.layout.my_example_fragment, container, false);

}
Amir Alagic
  • 1,780
  • 1
  • 12
  • 10
  • 1
    this worked for me too, thanks!. i looked at a half dozen tutorials including the official android docs and nowhere was this mentioned. such critical omission has sadly been the rule more than the exception in my journey learning android development.... – Nathaniel Hoyt Dec 23 '20 at 03:20
55

Use menu.clear() before inflating menus.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    menu.clear();
    inflater.inflate(R.menu.mnulayout, menu);
}
Abhinaw Sharma
  • 676
  • 5
  • 8
  • +1, If you have a main activity that switches between multiple fragments, and you are trying to use a custom `` as an action bar for one of those fragments, this is the solution that you want. – David Gay Jan 08 '18 at 03:25
14

first of all your fragment has to have in the onCreate

    setHasOptionsMenu(true);

and then you has to check that your activity DONT have the NoActionBar like theme its a little of tricky but if your activity has that theme doesn't matter where you call the setHasOptionsMenu(true) you fragment wont paint her

cubo1123
  • 151
  • 1
  • 4
8

I had the same problem. I fixed it by using the showAsAction in the item applied to myApp context:

<menu xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:myapp="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/action_refresh"
          android:icon="@drawable/ic_refresh"
          android:title="refresh"
          android:visible="true"
          myapp:showAsAction="ifRoom|withText"/>
</menu>

Sorry it is too late for you, but it may be useful for other people.

aglour
  • 924
  • 8
  • 15
  • 3
    Note: Using `android:showAsAction` seems to have no effect when using the support Fragment, so setting up the second namespace with res-auto is critical. Thanks for the help. – Eric Brynsvold Dec 31 '13 at 22:54
  • +1 @aglour for this nugget, had everything else setup and was using Support V4 as mentioned by Eric, cannot see how would have fixed this otherwise, thank you. – WickedW Feb 09 '15 at 15:17
7

This actually works for me and could be your solution as well.

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);
    setHasOptionsMenu(true);
}
Shruti
  • 803
  • 9
  • 26
Cockpit Aliens
  • 411
  • 6
  • 18
6

This happens because your device have hardware menu button. Therefore value of the variable "sHasPermanentMenuKey" is true in ViewConfiguration hasPermanentMenuKey(). You have to put the value of this variable false using reflection. Example:

// this method force showing menu button in device with hardware menu button
private void showOverflowMenu(FragmentActivity activity) {
    try {
        ViewConfiguration config = ViewConfiguration.get(activity);
        Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
        if (menuKeyField != null) {
            menuKeyField.setAccessible(true);
            menuKeyField.setBoolean(config, false);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

NOTE: use this method in onCreate() of activity not in method onCreate() of fragment.

Orgazm pionerki
  • 336
  • 4
  • 11
4

Make sure you set setSupportActionBar(youtoolbar) if you use a Toolbar in your activity.

riyaz-ali
  • 8,677
  • 2
  • 22
  • 35
Michael Dovoh
  • 121
  • 1
  • 4
3

When registering for options/context menus in fragments, you generally need to wait until the onActivityCreated() call to ensure that there is an activity to tie the menu to. Try the fix suggested here and see if it helps:

Context menu from a ListFragment

Community
  • 1
  • 1
jsmith
  • 4,847
  • 2
  • 32
  • 39
  • Hey jsmith, this is about contextual menus, I am talking about the actionbar menu items or hardware button menu items respectively. – El Duderino Aug 23 '12 at 13:02
  • 2
    Yes, I understood that. In reading the issue, it seemed to imply that you call setHasOptionsMenu(true) in the fragments onCreate. I'm suggesting you move it to the onActivityCreated() method for both fragments. This applies to options menus and context menus. – jsmith Aug 23 '12 at 14:58
2

For a fragment class in order for you to see your menu add sethasoptionsmenu(true) in either onCreateView() method or onCreateAcivity() method. But I added mine to onCreateView() method. Hope it helps someone

Ekenne Chilex
  • 45
  • 2
  • 8
1

An Options Menu may be hidden, but work. You can check this by long pressing the hardware button "Recent Apps".

In addition to the mentioned reasons for the hidden menu, there may be a theme without an action bar specified in the AndroidManifest.xml

    <application
        ...
        android:theme="@style/Theme.Design.NoActionBar"
        ...
    </application>
Vasil Li
  • 21
  • 4
1

This Code explains the Solution for showing the Fragment OnOptionItem Selection Items. and OnClicklistner of the Items in the optionMenu

If application is using Custom Toolbar for each individual Fragment.

FragmentTest.java

public class FragmentTest extends BaseFragmentHelper {
    public static final String TAG = FragmentRegistration.class.getSimpleName();
    View testFragmetnView;
   
    Toolbar toolbarRegistration;

    @Override
    public void onAttachFragment(@NonNull Fragment childFragment) {
        super.onAttachFragment(childFragment);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        testFragmetnView= inflater.inflate(R.layout.test_layout, container, false);
        //Intialize Toolbar
        toolbarRegistration=(Toolbar) registrationFragmentView.findViewById(R.id.toolbarRegistration_id);
        //inflate Menu layout
        toolbarRegistration.inflateMenu(R.menu.menu_test);
        //onOption Menu OnClicklistner
        toolbarRegistration.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
           switch (item.getItemId()){
                case R.id.test1:{
                    Toast.makeText(getActivity(),"Test 1",Toast.LENGTH_SHORT).show();
                    break;
                }
                case R.id.test2:{
                    Toast.makeText(getActivity(),"Test 2",Toast.LENGTH_SHORT).show();
                    break;
                }
            }
            return false;
        }
    });
        return testFragmetnView;
    }

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

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onResume() {
        super.onResume();

    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public String toString() {
        return FragmentTest.class.getSimpleName();
    }
  }

test_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbarRegistration_id"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:contentInsetLeft="0dp"
        android:background="@color/purple_700"
        app:contentInsetStart="0dp">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ImageView
                android:id="@+id/imageView_toolbar_cancel_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/cancel_icon"
                android:layout_centerVertical="true"
                android:layout_marginLeft="5dp">
            </ImageView>
            <TextView
                android:id="@+id/toolbar_textViewheader_id"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="50dp"
                android:textColor="@color/white"
                android:textStyle="bold"
                android:text="Registration"
                android:textSize="20dp">
            </TextView>
        </RelativeLayout>
    </androidx.appcompat.widget.Toolbar>
</RelativeLayout>

menu_test

<?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/test1"
        android:title="Test 1"
        android:visible="true" />
    <item
        android:id="@+id/test2"
        android:title="Test 2"
        android:visible="true"
        />
</menu>
vinay shetty
  • 895
  • 1
  • 9
  • 15
0

Try to change onCreateOptionsMenu to onPrepareOptionsMenu in fragments, i had the same problem and as far as i remember this solved it for me...

Dimanoid
  • 6,999
  • 4
  • 40
  • 55
  • Changed it to @Override public void onPrepareOptionsMenu(Menu menu) { Log.i("FragCreateList","onPrepareOptionsMenu called"); MenuInflater inflater=new MenuInflater(getActivity()); inflater.inflate(R.menu.menu_fragcreatelist, menu); } but still nothing... nothing is showing. – El Duderino Aug 23 '12 at 11:49
  • Strange, I have activity with two fragments, classic schema, activity itself have a menu and each fragment have its own menu. I have onCreateOptionsMenu in activity and onPrepareOptionsMenu in fragments. And I have all three menus showed combined... – Dimanoid Aug 23 '12 at 12:16
  • Maybe we misunderstood, I don't want all my menus combined, I want those two separate menus shown in two separate fragments, but only one fragment shows a menu. I first had onCreateOptions in my Activity too, but moved all to fragments, as I thought it makes more sense. I just solved my problem with a different design approach, still I'd like to know why it doesn't work :) Thanks for the effort. – El Duderino Aug 23 '12 at 12:59
  • 1
    @EI Duderino same problem with u, how did u solve it? – famfamfam Apr 16 '19 at 03:52
0

Your activity needs to extend ActionBarActivity. You may have one that only extends Activity.strong text

ockley
  • 1
0

If none of the solution works then try following :

Add following line in onCreateView() method

setHasOptionsMenu(true)

Also add below line in onViewCreated() method

(activity as AppCompatActivity?)!!.setSupportActionBar(customToolbar as Toolbar?)

Where customToolBar is the id of the toolbar added in xml file

Mudit Goel
  • 196
  • 1
  • 5
0

If you are using custom Toolbar and cannot see the menu, then try following method :

private fun configureOverflowMenu(toolbar: Toolbar) {
    toolbar.inflateMenu(R.menu.menu_share)
    toolbar.setOnMenuItemClickListener {
        when (it.itemId) {
            R.id.menuShare -> {
                //Do something
                true
            }
            else -> false
        }
    }
}

and call this method as follows:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    configureOverflowMenu(customToolbar as Toolbar)
}
Mudit Goel
  • 196
  • 1
  • 5
-1

A very late addition as none of the suggestions above solved my problem. My device (2.3.5) had such a bad timing problem with the options menu that I had to go a different route and create the menu in the onprepare part using the inflater from the activity:

@Override
public void onPrepareOptionsMenu(Menu menu)
{
    if (Build.VERSION.SDK_INT < 11) {
        menu.clear();
        getActivity().getMenuInflater().inflate(R.menu.message_thread, menu);
    }
Carsten
  • 806
  • 5
  • 6