104

I have a toolbar as well as a navigation drawer. When I start my app, the toolbar and navigation drawer are created. When I click items in the navigation drawer, it starts new fragments and keeps the same toolbar. How do I basically add menu items to the toolbar such as search, add, edit when I start specific fragments? I don't want them at the start of the program, but created dynamically. Also, how would I be able to click these buttons and have them start other fragments. I want it so in one fragment, the edit button in the toolbar does a specific thing compared to the edit button in another fragment. Thanks!

Menu_toolbar:

<?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/edit"
    android:orderInCategory="1"
    android:title="Edit"
    app:showAsAction="always"
    android:icon="@drawable/pencil_icon"/>
<item android:id="@+id/add"
    android:orderInCategory="1"
    android:title="Add"
    app:showAsAction="always"
    android:icon="@drawable/plus_icon"/>

Toolbar:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="#10a1ff"
android:title="Home"
/>
Valentin Gavran
  • 341
  • 9
  • 21
Joe Eigi
  • 1,041
  • 2
  • 8
  • 8

12 Answers12

188

Add similar code to your fragments:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
    View v = inflater.inflate(R.layout.library_fragment, parent, false);
    setHasOptionsMenu(true);
    return v;
}


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

This way you can customize the menu for your fragments.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Gundu Bandgar
  • 2,593
  • 1
  • 17
  • 21
  • 20
    This is the correct answer because the call to setHasOptionsMenu(true) is required for the onCreateOptionsMenu method being called in the fragment. – John Slavick Jan 06 '16 at 15:15
  • 21
    Remember about calling `menu.clear()` in `onCreateOptionsMenu` - otherwise you'll inherit the menu from the parent, too. – Dart Dega Mar 01 '18 at 08:49
  • @DartDega where i put code to clear? Fragment or Activity sir, i am not seeing menuitem in my fragment – famfamfam Apr 16 '19 at 07:30
  • Does this work with API level 28 ? I still see the main activities menu items – ArdenDev Feb 05 '20 at 14:54
37

The best way to do it :

1. Find toolbar in Activity and set it as supportActionBar.

Toolbar actionBarToolBar = (Toolbar) findViewById(R.id.my_toobar);
setSupportActionBar(actionBarToolBar);

2. Then It will be a piece of cake to handle option menus for different fragments over a same Activity. Do following things in each fragment as you want:

In OnCreateView Method call

setHasOptionsMenu(true);

And Lastly,

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

And to manage menu items click, we have onOptionsItemSelected:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_search :
            Log.i("item id ", item.getItemId() + "");
        default:
            return super.onOptionsItemSelected(item);
    }
}
Prateek Gupta
  • 835
  • 10
  • 18
35

This is how to create menu dynamically: http://www.101apps.co.za/index.php/articles/using-toolbars-in-your-apps.html

Edited:

Toolbar actionBarToolBar = (Toolbar) findViewById(R.id.my_toobar);
setSupportActionBar(actionBarToolBar);
actionBarToolBar.setNavigationIcon(R.drawable.icon);
actionBarToolBar.setNavigationContextDescription(getResources().getString(R.string.desc);
actionBarToolBar.setLogo(R.drawable.other_icon);
actionBarToolBar.setLogoDescription(getResources().getString(R.string.other_desc);
actionBarToolBar.inflateMenu(R.menu.fragment_menu);
Allen Chan
  • 4,041
  • 2
  • 19
  • 16
27

The simplest option is to do

toolbar.inflateMenu(R.menu.fragment_menu);

and for handle click on menu item

toolbar.setOnMenuItemClickListener {
    when (it.itemId) {
        R.id.nav_example -> doThat()
    }
    true
}
Guillaume
  • 6,214
  • 2
  • 13
  • 14
11

Override onCreateOptionsMenu method in your every fragment.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.your_menu_xml, menu);
    super.onCreateOptionsMenu(menu, inflater);
}
Ellie Zou
  • 2,021
  • 2
  • 16
  • 21
  • @JoeEigi Why you want different toolbar? You can set different title and menus. – Ellie Zou Jun 09 '15 at 01:57
  • @JoeEigi yes, you can have custom menu by inflating custom menu xml. Call `setTitle()` can add titles. – Ellie Zou Jun 09 '15 at 02:14
  • @JoeEigi Seems you got the wrong context, have a look on this: http://stackoverflow.com/questions/26998455/how-to-get-toolbar-from-fragment – Allen Chan Jun 09 '15 at 02:18
  • 1
    I turned the actionbar off in my manifest, but still shows up in my activity layout above toolbar. How do I get rid of this – Joe Eigi Jun 09 '15 at 02:37
  • Yes, did that and still shows up in my layout but is moved out of view – Joe Eigi Jun 09 '15 at 02:52
  • @JoeEigi That's werid. You write `Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);setSupportActionBar(toolbar);` ? – Ellie Zou Jun 09 '15 at 05:18
7

I solved this issues correctly. My solution is as following code:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    mRootView = inflater.inflate(R.layout.fragment_order_history, container, false);
    //getActivity().invalidateOptionsMenu();


    setHasOptionsMenu(true);

    return mRootView;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.main, menu);
    super.onCreateOptionsMenu(menu, inflater);
}
Hai Rom
  • 1,751
  • 16
  • 9
  • Yes I showed the menu correctly. But how to hide this menu on fragment close, I mean When we switch to another fragment e.g. from a -> b, the menu of a still visible in toolbar of fragment b. – Zeeshan Ahmed Aug 01 '16 at 10:16
  • use setHasOptionsMenu(false) in onCreateView of fragment b. – Kannan_SJD Mar 08 '17 at 09:36
6

I had the same issue and I wanted to replace the toolbar menu accordingly to the fragment displayed.

The problem I'm now facing is that the menu is added to the previous one.

In order to show only the menu for the fragment, I suggest:

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

Hope it'll help.

Matteo Gariglio
  • 482
  • 5
  • 12
3

Below are the steps to show different menu options with different fragments.

Step1: Call setHasOptionsMenu(true)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        setHasOptionsMenu(true)
        super.onViewCreated(view, savedInstanceState)

    }

Step2: Inflate your fragment related option menu items.

override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
    // To clear previously added menu items
    menu?.clear()
    inflater?.inflate(R.menu.your_fragment_menu, menu)
    super.onCreateOptionsMenu(menu, inflater)
}
takharsh
  • 2,258
  • 1
  • 21
  • 26
3

Using new MaterialToolbar it's very easy to create an overflow menu and use to:

<com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="?attr/actionBarSize"
        app:navigationIcon="@drawable/ic_menu"
        app:menu="@menu/main_menu"/>

and then in code to set OnCLick Listeners just add this:

toolbar.setOnMenuItemClickListener {
            // .. DO SOMETHING HERE
            false
        }
Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38
1

Inside XML add this line

app:menu="@menu/main_menu"
Mohamed AbdelraZek
  • 2,503
  • 4
  • 25
  • 36
  • 1
    Actually you're right! You can specify it by xml and then in the fragment: ``` override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) toolBar.setNavigationOnClickListener { activity?.onBackPressed() } searchView = toolBar.menu.findItem(R.id.action_search).actionView as SearchView searchView.setOnQueryTextListener(this) } ``` – user3193413 May 21 '20 at 13:37
0

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

No one mentioned this method here so here it is. This is a better approach when you don't have many items for each fragment and have the same parent activity. It's taken from this answer.

0

i had the same problem, what worked for me was this: in my case i have 1 toolbar in the main activity and all fragments will use that toolbar by just adding new menu items to the toolbar

  1. set the support action bar in the main activity oncreate method

    MaterialToolbar maintoolbar=findViewById(R.id.topAppBar); setSupportActionBar(maintoolbar);

  2. add this in fragment oncreateview

    setHasOptionsMenu(true);

  3. override the oncreateoptionsmenu method in your fragment

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

  4. handle options menu clicks in your fragment

    @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case ...: break; default: return super.onOptionsItemSelected(item); } ... }