Using Toolbar with Fragments
Asked Answered
I

6

48

I am trying to create a viewpager that swipes through 3 different fragments each with a different toolbar. I have implemented the new toolbar in an activity before and got it to work however I am trying to get it to work with fragments

Here is the fragment code

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout resource that'll be returned
    View rootView = inflater.inflate(R.layout.fragment_home, container, false);


    mToolbar = (Toolbar) rootView.findViewById(R.id.toolbar_home);
    if (mToolbar != null) {
        setSupportActionBar(mToolbar);
    }
    mToolbar.setTitle(null);

    return rootView;
}

I am extending my fragment with Fragment, however I am getting the error

Cannot resolve method setSupportActionBar

I am not sure how to resolve this, if I remove the setSupportActionBar code will it stop working with certain devices?

Innate answered 12/3, 2015 at 21:52 Comment(4)
Is there an issue with having it in your activity layout and setting it in your activity?Become
each toolbar for each viewpager will have a different color and different menus, so i thought it would be better to control them with the fragmentsInnate
Hang on, isn't the whole point in this scenario not to set the ToolBar as ActionBar? Since your intention is for every fragment to have its own ToolBar (which swipes along with the other content of the fragment), we're talking about the 'standalone' (scroll down to the 'standalone' section) usage of the widget.Diatomaceous
The menu part is already supported with different menu xmls and attaching via onCreateOptionsMenu. The color part can be done within the onAttach using something like #25082206Become
P
88

Fragments don't have such method setSupportActionBar(). ActionBar is a property of Activity, so to set your toolbar as the actionBar, your activity should extend from ActionBarActivity and then you can call in your Fragment:

 ((ActionBarActivity)getActivity()).setSupportActionBar(mToolbar);

UPDATE

If you're using AppCompatActivity :

 ((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar);
Pastelist answered 12/3, 2015 at 22:14 Comment(3)
In my case this does not replace the actionbar of the Mainactivity but it gives the Toolbar a title like in the Mainactivity.Heisler
@Pastelist Hey in your above answer you forgot to write "()" after getActivity. so please add this so other people will not get confuse.Ancylostomiasis
Shifting SupportActionBar from Activity's toolbar to Fragments toolbar may loose Support for Activity toolbar. what if you need to update the Activity toolbar once inside Fragment with shifted SupportActionBar ? :).Cabana
C
53

I have seen a lot of answers mentioning to setSupportActionBar for toolbar inside Fragment but this approach may go wrong if you are having a a toolbar in Activity and a separate Toolbar in Fragment.

  1. As you shift setSupportActionBar from Activity's Toolbar to Fragment's toolbar, You may face duplication of MenuItem even you try to override using setHasOptionsMenu(true).
  2. Secondly If you want to update Activity's Toolbar you see your changes are not reflected because of setSupportActionBar inside your Fragment.

So in order to avoid this I recommend to use toolbar methods like this inside fragment to inflate menu and use

 toolbar = (Toolbar) view.findViewById(R.id.toolbar_frag);
    toolbar.inflateMenu(R.menu.frag_menu_items);
    Menu menu = toolbar.getMenu();

and use Toolbar.OnMenuItemClickListener interface to receive with menuItems click events.

Edit (Section Copied from MrEngineer13 answer)

and if you are worried about the back button you can set it like this

toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_action_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
       //What to do on back clicked
   }
});
Cabana answered 12/8, 2017 at 18:14 Comment(3)
Hi Faisal Naseer can you explain it in detail becoz i m facing the same problem that you describe.Statolith
sure whats the issue at your end have you tried the above approach.Cabana
I have resolved the issue using your code by RND thanks for your feedback. Actually i have only one Activity and rest of all fragment in my app. So updating the toolbar with option menu in each fragment occur the issue. But with your code its working fine Thankyou.Statolith
U
22

Base on @Faisal Naseer answer. Here is the full example (with few notes) for using custom Toolbar with navigation and menu in Fragment

fragment_home.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"">

    ...
    <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar_home"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:title="Home" /> 

</androidx.constraintlayout.widget.ConstraintLayout>

HomeFragment.kt

class HomeFragment : BaseFragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        // setHasOptionsMenu(true): don't need this anymore
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_home, container, false)
    }

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

        toolbar_home.setNavigationIcon(R.drawable.ic_back) // need to set the icon here to have a navigation icon. You can simple create an vector image by "Vector Asset" and using here
        toolbar_home.setNavigationOnClickListener {
            // do something when click navigation
        }

        toolbar_home.inflateMenu(R.menu.menu_home)
        toolbar_home.setOnMenuItemClickListener {
            when (it.itemId) {
                R.id.action_add -> {
                    // do something
                    true
                }
                R.id.action_update -> {
                    // do something
                    true
                }
                else -> {
                    super.onOptionsItemSelected(it)
                }
            }
        }
    }
}

menu_home.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/action_add"
        android:title="@string/add_device"
        app:showAsAction="never" />

    <item
        android:id="@+id/action_update_room"
        android:title="@string/update_room"
        app:showAsAction="never" />

</menu>

Hope it help

enter image description here

Uno answered 25/1, 2019 at 8:55 Comment(4)
Hi, the inflate menu working very well but setOnMenuItemClickListener doesn't work Need help.Elope
even for single menu it shows overflow menu. I dont want overflow menu, what can done to achieve that?Dineric
how about if I don't wanna back arrow, how can I hide it?, I need only three dotsImperforate
@Phan, Where is BaseFragment can you provide me that also? Because toolbar_home is not finding here in this example.Colima
A
9

With the new AppCompatActivity you should call it instead of ActionBarActivity:

((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
Albemarle answered 1/9, 2015 at 16:37 Comment(0)
E
2

You can add toolbar in Fragments using this

 ((YOUR_ACTIVITY) getActivity()).getDelegate().setSupportActionBar(toolbar);
Emiliaemiliaromagna answered 24/8, 2016 at 6:45 Comment(0)
B
1

I use Kotlin. In my case Activity is a child class of AppCompatActivity and theme of activity is inherited from Theme.MaterialComponents.DayNight.NoActionBar

So my Activity doesn't have action bar, but my Fragment do.

I will show you how to use toolbar with defined menu as a SupportActionBar in fragment

This is my Toolbar

<com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:fitsSystemWindows="true"
            app:navigationContentDescription="Back to the previous question"
            android:background="?attr/colorPrimary"
            tools:title="@string/posts" />

This is my Fragment's methods:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        (context as AppCompatActivity).setSupportActionBar(_bind?.toolbar)
        setHasOptionsMenu(true)
}
    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        inflater.inflate(R.menu.toolbar_menu_post_list, menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when(item.itemId)
        {
            R.id.add -> {
                val post = Post()
                postListViewModel.addPost(post)
                callbacks?.onItemSelected(post.id)
                return true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }

Beyer answered 6/7, 2021 at 11:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.