How to add Options Menu to Fragment in Android
Asked Answered
Y

25

459

I am trying to add an item to the options menu from a group of fragments.

I have created a new MenuFragment class and extended this for the fragments I wish to include the menu item in. Here is the code:

Java:

public class MenuFragment extends Fragment {

    MenuItem fav;

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

    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

Kotlin:

class MenuFragment : Fragment {

    lateinit var fav: MenuItem

    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

For some reason the onCreateOptionsMenu appears not to run.

Yt answered 29/11, 2011 at 9:48 Comment(5)
maybe a silly question... you press the menu button right?Adenovirus
..lol...yes I have pressed the menu button, I have also tried it with and without: fav.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);Yt
Hi, maybe this thread will help you or check the api demo for a working example.Childlike
droidmentor.com/how-to-use-fragment-specific-menu-in-androidOdense
There is a new of doing this since androidx.activity:activity:1.4.0. See my new answer: https://mcmap.net/q/80214/-how-to-add-options-menu-to-fragment-in-androidGraupel
C
682

Call the super method:

Java:

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

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater);
    }

Kotlin:

    override fun void onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater)
    }

Put log statements in the code to see if the method is not being called or if the menu is not being amended by your code.

Also ensure you are calling setHasOptionsMenu(boolean) in onCreate(Bundle) to notify the fragment that it should participate in options menu handling.

Crissum answered 29/11, 2011 at 10:29 Comment(13)
Thanks for the help, I added the super method, and realised I had removed the @Override so added this back in, eclipse threw an error so I replaced the MenuInflater to import android.view.MenuInflater; instead of import android.support.v4.view.MenuInflater; and now all is workingYt
not calling setHasOptionsMenu(true) in the Fragment's onCreate has gotten me twice nowBrownell
I was transferring my Activity to a Fragment and ran into this issue. The method signature has changed from public boolean to public void and the arguments have also changed. Make sure to take note of this!Scan
Note that Fragment.onCreateOptionsMenu(Menu, MenuInflater) is an empty method, so calling super is not required at all. The only mistake here was the wrong method signature and possibly a missing setHasOptionsMenu() in onCreate()Courage
That may be so but it is still worth mentioning for the people using Activities instead of Fragments and by the upvotes, many people agree and were helped by this answer.Crissum
You know, in Java a method is identified, in part, with a name (as you used), and a CLASS. So, please, when you suggest to override a method, please, please give the class. Especially as there are two objects that may be manipulated (Fragmentand Activity, and the Fragment usually has its onCreateView() method overridden while the Activity has its onCreate() method overridden).Gainly
The question already stated that the Class was Fragment as part of its text and in the code sample. There was no need to repeat it.Crissum
is it possible to first remove all existing items from the menu then add an item.Nakamura
@Saifee please open your own question as what you asked is not relevant to this one.Crissum
I'm using a Toolbar and had to call setHasOptionsMenu(true) in onCreateView() instead onCreate() to get it done.Ascomycete
Replace super.onCreateOptionsMenu with inflater.inflate(R.menu.menu_custom, menu);Pachisi
There is a new of doing this since androidx.activity:activity:1.4.0. See my new answer: https://mcmap.net/q/80214/-how-to-add-options-menu-to-fragment-in-androidGraupel
onCreateOptionMenu is deprected. how can we acheive this with addMenuProvider ?Ur
G
219

I had the same problem, but I think it's better to summarize and introduce the last step to get it working:

  1. Add setHasOptionsMenu(true) method in your Fragment's onCreate(Bundle savedInstanceState) method.

  2. Override onCreateOptionsMenu(Menu menu, MenuInflater inflater) (if you want to do something different in your Fragment's menu) and onOptionsItemSelected(MenuItem item) methods in your Fragment.

  3. Inside your onOptionsItemSelected(MenuItem item) Activity's method, make sure you return false when the menu item action would be implemented in onOptionsItemSelected(MenuItem item) Fragment's method.

An example:

Activity

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Do Activity menu item stuff here
            return true;

        case R.id.fragment_menu_item:

            // Not implemented here
            return false;
        default:
            break;
    }

    return false;
}

Fragment

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Not implemented here
            return false;
        case R.id.fragment_menu_item:

            // Do Fragment menu item stuff here
            return true;

        default:
            break;
    }

    return false;
}
God answered 19/8, 2013 at 16:52 Comment(7)
On a viewPager on some devices the menu is only shown the second time the you go to the fragmentSeaquake
@Marco HC your code works fine. But what if i want to hide some of the menu for Activity or for Fragment? You have mention about where to implement which option menu (In activity and fragment). But what if i want to hide some menu?Successful
@iDroidExplorer just keep a reference to that MenuItem and set visibility to gone or invisible. It's that your question?God
@iDroidExplorer I tried his code and I don't know how but it automatically hide the menu when I switch to other fragments.Emlen
How to show Option Menu from Fragment with fragment's button click event?Erbil
keeps on forgetting to add this... setHasOptionsMenu(true);Theone
Thank you for the callout in number 3 🙏Prostatectomy
T
162

If you find the onCreateOptionsMenu(Menu menu, MenuInflater inflater) method is not being invoked, make sure you call the following from the Fragment's onCreate(Bundle savedInstanceState) method:

setHasOptionsMenu(true)
Terebinthine answered 3/10, 2012 at 6:16 Comment(4)
It gives me Error like NullPointerExceptionStout
Good point. I was calling the setHasOptionMenu method from the static newInstance method. As I was only attaching my fragment when savedInstanceState was null, when the screen configuration changed the menu would not be created. The onCreate method of the fragment is the correct place where to set setHasOptionMenu to true.Abercromby
I'm using a Toolbar and had to call setHasOptionsMenu(true) in onCreateView() instead onCreate() to get it done.Ascomycete
'setHasOptionsMenu(Boolean): Unit' is deprecated. Deprecated in Java. This method is no longer needed when using a MenuProvider to provide a Menu to your activity, which replaces onCreateOptionsMenu as the recommended way to provide a consistent, optionally Lifecycle-aware, and modular way to handle menu creation and item selection.Afra
M
82

If you need a menu to refresh a webview inside a specific Fragment, you can use:

Fragment:

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    // TODO Add your menu entries here
    inflater.inflate(R.menu.menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.exit:
        System.exit(1);
        break;

    case R.id.refresh:
        webView.reload();
        break;
    }
    return true;

}

menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/exit" android:title="Exit" android:icon="@drawable/ic_action_cancel" />
    <item android:id="@+id/refresh" android:title="Refresh" android:icon="@drawable/ic_action_refresh" />
</menu>
Miner answered 5/11, 2014 at 15:54 Comment(1)
This is a great answer, where I was looking for a way to merge app bar from activity and additional options coming from fragment, thanks!Redouble
S
49

TL;DR

Use the android.support.v7.widget.Toolbar and just do:

toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
    onOptionsItemSelected(it)
}

Standalone Toolbar

Most of the suggested solutions like setHasOptionsMenu(true) are only working when the parent Activity has the Toolbar in its layout and declares it via setSupportActionBar(). Then the Fragments can participate in the menu population of this exact ActionBar:

Fragment.onCreateOptionsMenu(): Initialize the contents of the Fragment host's standard options menu.

If you want a standalone toolbar and menu for one specific Fragment you can to do the following:

menu_custom_fragment.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_save"
        android:title="SAVE" />
</menu>

custom_fragment.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    ...

CustomFragment.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(layout.custom_fragment, container, false)
    val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
    toolbar.inflateMenu(R.menu.menu_custom_fragment)
    toolbar.setOnMenuItemClickListener {
        onOptionsItemSelected(it)
    }
    return view
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.menu_save -> {
            // TODO: User clicked the save button
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Yes, it's that easy. You don't even need to override onCreate() or onCreateOptionsMenu().

PS: This is only working with android.support.v4.app.Fragment and android.support.v7.widget.Toolbar (also be sure to use AppCompatActivity and an AppCompat theme in your styles.xml).

Stenographer answered 22/6, 2018 at 15:11 Comment(3)
really helped a lot to meHeiskell
Is there an alternative to onPrepareOptionsMenu in this case?Oppress
This was my problem! Thanks!Nobody
B
27

In the menu.xml you should add all the menu items. Then you can hide items that you don't want to see in the initial loading.

menu.xml

<item
    android:id="@+id/action_newItem"
    android:icon="@drawable/action_newItem"
    android:showAsAction="never"
    android:visible="false"
    android:title="@string/action_newItem"/>

Add setHasOptionsMenu(true) in the onCreate() method to invoke the menu items in your Fragment class.

FragmentClass.java

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

You don't need to override onCreateOptionsMenu in your Fragment class again. Menu items can be changed (Add/remove) by overriding onPrepareOptionsMenumethod available in Fragment.

@Override
public void onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_newItem).setVisible(true);
    super.onPrepareOptionsMenu(menu);

}
Babbling answered 29/11, 2011 at 9:48 Comment(0)
S
21

In my case, here is the steps.

Step-1

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

    // Here notify the fragment that it should participate in options menu handling.
    setHasOptionsMenu(true);
}

Step-2

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // First clear current all the menu items
    menu.clear();

    // Add the new menu items
    inflater.inflate(R.menu.post_stuff, menu);

    super.onCreateOptionsMenu(menu, inflater);
}

Step-3

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.post_stuff:
            Log.d(TAG, "Will post the photo to server");
            return true;
        case R.id.cancel_post:
            Log.d(TAG, "Will cancel post the photo");
            return true;
        default:
            break;
    }
    return super.onOptionsItemSelected(item);
}
Slimy answered 6/2, 2018 at 23:47 Comment(2)
I already had menu on main activity, using menu.clear() cleared previous menu. Worked for me :)Cahn
i have ViewPager with Fragments, the menu.clear() was the missing part thanks!Hammurabi
G
21

There is a new way of doing this since androidx.activity:activity:1.4.0

You are supposed to use the MenuProvider API.

It is used as follows:

Instead of calling super.setHasOptionMenu and implementing onCreateOptionsMenu you are supposed to call addMenuProvider in onViewCreated.

An Example:

class ExampleFragment : Fragment(R.layout.fragment_example) {

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    // The usage of an interface lets you inject your own implementation
    val menuHost: MenuHost = requireActivity()
  
    // Add menu items without using the Fragment Menu APIs
    // Note how we can tie the MenuProvider to the viewLifecycleOwner
    // and an optional Lifecycle.State (here, RESUMED) to indicate when
    // the menu should be visible
    menuHost.addMenuProvider(object : MenuProvider {
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        // Add menu items here
        menuInflater.inflate(R.menu.example_menu, menu)
      }

      override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Handle the menu selection
        return true
      }
    }, viewLifecycleOwner)
  }

source: Activity Changelog

Graupel answered 22/7, 2022 at 12:48 Comment(3)
latest and modern way to add menu with fragment.. 👍Violoncellist
@Graupel val menuHost: MenuHost = requireActivity() ? can you elaborate this ? MenuHost given type, but you set FragmentActivity insteadLoathsome
@GideonSteven MenuHost is just an interface which is implemented by FragmentActivity. It would also be possible to make menuHost FragmentActivity and call these methods directly.Graupel
H
17

You need to use menu.clear() before inflating menus.

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

and

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }
Heterophyllous answered 26/3, 2015 at 13:36 Comment(2)
This is correct when you want different menus in different fragments and you are adding fragments instead of replacing them.Poorly
Thank you! menu.clear() help me remove the menu option of Activity.Utica
P
8

If you want to add your menu custom

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

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_custom, menu);
}
Pressroom answered 23/6, 2016 at 18:26 Comment(1)
what if there is a tab view and you want to inflate different menus for each fragment?Ceja
G
7

I've had the same problem, my fragments were pages of a ViewPager. The reason it was happening is that I was using child fragment manager rather than the activity support fragment manager when instantiating FragmentPagerAdapter.

Gerrygerrymander answered 26/7, 2013 at 15:4 Comment(0)
Z
3

Menu file:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/play"
        android:titleCondensed="Speak"
        android:showAsAction="always"
        android:title="Speak"
        android:icon="@drawable/ic_play">
    </item>
    <item
        android:id="@+id/pause"
        android:titleCondensed="Stop"
        android:title="Stop"
        android:showAsAction="always"
        android:icon="@drawable/ic_pause">
    </item>
</menu>

Activity code:

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            Toast.makeText(getApplicationContext(), "speaking....", Toast.LENGTH_LONG).show();
            return false;

        case R.id.pause:
            Toast.makeText(getApplicationContext(), "stopping....", Toast.LENGTH_LONG).show();
            return false;

        default:
            break;
    }

    return false;
}

Fragment code:

@Override

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            text = page.getText().toString();
            speakOut(text);

            // Do Activity menu item stuff here
            return true;

        case R.id.pause:
            speakOf();

            // Not implemented here
            return true;

        default:
            break;
    }
    return false;
}
Zloty answered 21/11, 2015 at 16:48 Comment(0)
B
3

Your code is fine. Only the super was missing in the method :

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // TODO add your menu : 
    inflater.inflate(R.menu.my_menu, menu);
    //TODO call super
    super.onCreateOptionsMenu(menu, inflater);
}
Boxfish answered 26/9, 2017 at 7:57 Comment(0)
G
2

I was getting crazy because none of the answers here worked for me.

To show the menu I had to call: setSupportActionBar(toolbar)

Done!

Note: if your toolbar view isn't in the same activity layout you can't use the call above directly from your activity class, in this case you'll need to get that activity from your fragment class and then call the setSupportActionBar(toolbar). Remembering: your activity class should extends the AppCompatActivity.

Hope that this answer help you.

Greaseball answered 24/1, 2018 at 14:42 Comment(0)
S
2

Set setHasMenuOptions(true) works if application has a theme with Actionbar such as Theme.MaterialComponents.DayNight.DarkActionBar or Activity has it's own Toolbar, otherwise onCreateOptionsMenu in fragment does not get called.

If you want to use standalone Toolbar you either need to get activity and set your Toolbar as support action bar with

(requireActivity() as? MainActivity)?.setSupportActionBar(toolbar)

which lets your fragment onCreateOptionsMenu to be called.

Other alternative is, you can inflate your Toolbar's own menu with toolbar.inflateMenu(R.menu.YOUR_MENU) and item listener with

toolbar.setOnMenuItemClickListener {
   // do something
   true
}
Schematize answered 10/9, 2020 at 18:8 Comment(1)
This was why my menu wouldn't show up no matter what I did. Solution worked, thanks!!!!Nobody
B
2

Now on 2022, Google deprecated setHasOptionsMenu and you should use MenuProvider instead. In my experience, I got NoSuchMethodException on some android 11, 12 when I used setHasOptionsMenu method.

This method is no longer needed when using a MenuProvider to provide a Menu to your activity, which replaces onCreateOptionsMenu as the recommended way to provide a consistent, optionally Lifecycle-aware, and modular way to handle menu creation and item selection.

This is how you add menu to your activity/fragment atm:

/**
  * Using the addMenuProvider() API directly in your Activity
  **/
class ExampleActivity : ComponentActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Add menu items without overriding methods in the Activity
   addMenuProvider(object : MenuProvider {
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        // Add menu items here
        menuInflater.inflate(R.menu.example_menu, menu)
      }

      override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Handle the menu selection
        return true
      }
    })
  }
}

/**
  * Using the addMenuProvider() API in a Fragment
  **/
class ExampleFragment : Fragment() {

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    // The usage of an interface lets you inject your own implementation
    val menuHost: MenuHost = requireActivity()
  
    // Add menu items without using the Fragment Menu APIs
    // Note how we can tie the MenuProvider to the viewLifecycleOwner
    // and an optional Lifecycle.State (here, RESUMED) to indicate when
    // the menu should be visible
    menuHost.addMenuProvider(object : MenuProvider {
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        // Add menu items here
        menuInflater.inflate(R.menu.example_menu, menu)
      }

      override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
        // Handle the menu selection
        return true
      }
    }, viewLifecycleOwner, Lifecycle.State.RESUMED)
  }

Here's reference link.

Ah, for lazy one as me, you must add this as well:

dependencies {
    val activity_version = "1.5.1"

    // Java language implementation
    implementation("androidx.activity:activity:$activity_version")
    // Kotlin
    implementation("androidx.activity:activity-ktx:$activity_version")
}

Berrie answered 23/8, 2022 at 16:21 Comment(0)
V
1

Setting the options menu after creating the fragment view worked well for me.

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setHasOptionsMenu(true);        
}
Virilism answered 8/11, 2014 at 5:49 Comment(0)
R
1

My problem was slightly different. I did everything right. But I was inheriting the wrong class for the activity hosting the fragment.

So to be clear, if you are overriding onCreateOptionsMenu(Menu menu, MenuInflater inflater) in the fragment, make sure your activity class which hosts this fragment inherits android.support.v7.app.ActionBarActivity (in case you would want to support below API level 11).

I was inheriting the android.support.v4.app.FragmentActivity to support API level below 11.

Rhinarium answered 19/4, 2015 at 19:23 Comment(0)
H
1

One thing I would add to this and the reason it was not working for me.

It is similar to Napster's answer.

  1. Make sure your fragment's hosting activity extends AppCompatActivity, not FragmentActivity!

    public class MainActivity extends AppCompatActivity {
    
    }
    

    From the Google Reference Documentation for FragmentActivity:

    Note: If you want to implement an activity that includes an action bar, you should instead use the ActionBarActivity class, which is a subclass of this one, so allows you to use Fragment APIs on API level 7 and higher.

  2. To update Napster's answer -- ActionBarActivity now being deprecated, use AppCompatActivity instead.

  3. When using AppCompatActivity, also make sure you set "the activity theme toTheme.AppCompat or a similar theme" (Google Doc).

Note: android.support.v7.app.AppCompatActivity is a subclass of the android.support.v4.app.FragmentActivity class (see AppCompatActivity ref doc).

Hickok answered 22/10, 2015 at 23:54 Comment(0)
L
1

In your menu folder make a .menu xml file and add this xml

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

In your fragment class overide this method and

implement SearchView.OnQueryTextListener    in your fragment class



@Override
 public void onViewCreated(View view, Bundle savedInstanceState) {    
  super.onViewCreated(view, savedInstanceState);
  setHasOptionsMenu(true);

}

Now just setup your menu xml file in fragment class

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

    final MenuItem item = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView)    
    MenuItemCompat.getActionView(item);


    MenuItemCompat.setOnActionExpandListener(item,
            new MenuItemCompat.OnActionExpandListener() {
                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    // Do something when collapsed

                    return true; // Return true to collapse action view
                }

                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    // Do something when expanded
                    return true; // Return true to expand action view
                }
            });

}
Lancey answered 10/9, 2016 at 11:27 Comment(0)
B
0

If all of the above does not work, you need to debug and make sure function onCreateOptionsMenu has been called (by placing debug or write log...)

If it's not run, maybe your Android theme is not supporting the action bar. Open AndroidManifest.xml and set the value for android:theme with theme support action bar:

 <activity
     android:name=".MainActivity"
     android:label="@string/app_name"
     android:theme="@style/Theme.AppCompat">
Butterfield answered 23/5, 2016 at 6:47 Comment(0)
D
0

on your onCreate method add setHasOptionMenu()

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

Then override your onCreateOptionsMenu

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    menu.add("Menu item")
            .setIcon(android.R.drawable.ic_delete)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
Dippy answered 19/5, 2017 at 4:59 Comment(0)
S
0

This is what I did to hide and unhide ALL the menu options when the fragment is loaded and destroyed, respectively. It takes the risk out of pointing to null for R.id.your_menu_item and allowed me to reuse the fragment elsewhere.

lateinit var optionsMenu: Menu

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
    menu.iterator().forEach {
        it.isVisible = false
    }
    optionsMenu = menu
    super.onCreateOptionsMenu(menu, inflater)
}

override fun onDestroyView() {
    optionsMenu.iterator().forEach {
        it.isVisible = true
    }
    super.onDestroyView()
}
Shoelace answered 22/7, 2021 at 18:53 Comment(0)
E
0

In case none of the options above work for you, try this in your fragment:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 
....
        toolBar = rootView.findViewById(R.id.import_contacts_toolbar)
        toolBar?.title = "Your title"
        toolBar?.subtitle = "yor subtitile"
        contactsActivity().setSupportActionBar(toolBar)
        toolBar?.inflateMenu(R.menu.import_contacts_menu)
...
}



    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.1 -> {

                return true
            }
            R.id.2 -> {

                return true
            }
        }
    
        return false
    }





    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        menu.clear()
        inflater.inflate(R.menu.import_contacts_menu, menu)
        super.onCreateOptionsMenu(menu, inflater)

        val search = menu.findItem(R.id.action_search)
        val searchView = search.actionView as SearchView
        searchView.requestFocus()

        val txtSearch = searchView.findViewById<View>(androidx.appcompat.R.id.search_src_text) as EditText
        txtSearch.hint = "Search..."
        txtSearch.setHintTextColor(Color.WHITE);
        txtSearch.setTextColor(Color.WHITE)

        try {
            val f: Field = TextView::class.java.getDeclaredField("mCursorDrawableRes")
            f.setAccessible(true)
            f.set(txtSearch, R.drawable.search_edit_text_cursor)
        } catch (ignored: Exception) {
            Log.d(TAG, "failed to expose cursor drawable $ignored")
        }

        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String): Boolean {
                return false
            }

            override fun onQueryTextChange(newText: String): Boolean {

                return true
            }
        })
        searchView.setOnCloseListener {
            
        }
    }

In my case I had a search menu item which was set to always visible. This is the xml for it:

<?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_search"
        app:showAsAction="always"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        android:title="Search"/>

    <item android:id="@+id/1"
        android:title="1">
    </item>

    <item android:id="@+id/2"
        android:title="2">
    </item>
</menu>
Expurgatory answered 18/5, 2022 at 10:28 Comment(0)
S
0

Here's how to do it with a custom toolbar in a fragment. It is similar to the method by mbo but with the deprecated method replaced.

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    this.rootView = inflater.inflate(R.layout.fragment_study_list, container, false) as DrawerLayout



    // Set the menu
    val toolbar = this.rootView.findViewById<Toolbar>(R.id.studylist_toolbar)

    toolbar.addMenuProvider(object : MenuProvider {

        override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
            // Add menu items here
            menuInflater.inflate(R.menu.studylist_menu, menu)
        }

        override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
            // Handle the menu selection

            Log.d("CONJUU","Menu clicked")

            return true
        }
    }, viewLifecycleOwner, Lifecycle.State.RESUMED)
}
Specification answered 2/3, 2023 at 13:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.