12

The Problem

I have a navigation drawer with different fragments. There is a default toolbar every Fragment should use, except of one Fragment which needs a collapsing Toolbar.

My Question

How can I switch between the toolbars for the fragments ?

Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
Mayr Technologies
  • 725
  • 3
  • 10
  • 19

5 Answers5

10

It seems you want to achieve something like this.

Nothing fancy

I have made an activity with common toolbar. when switching to the collapsing toolbar fragment I've made the toolbar transparent and fragment's toolbar takes over. The toolbar's color remains the same on switching to other fragments.

This allows you to manage complete collapsing toolbar's layout structure in xml and logic remains in Fragment.

Hope this will help. Refer the gif linked.

Gist for gif

Ankush
  • 1,888
  • 20
  • 22
  • can you provide us with the code ? how you set toolbar transparent and when? – Mycoola Dec 07 '17 at 11:30
  • Gist is attached. You can access it at https://gist.github.com/groverankush/9d09fbba07879790d5395434fda1e2d4 – Ankush Dec 07 '17 at 13:00
  • i went through the gist and put it together and it does work, there is a comment on the gist suggesting this creates 2 toolbars but thats not the case this does work, however it does have an issue with collapsing toolbar titles not knowing where the drawer toggle is so ive set the title to collapse to the center, – martinseal1987 Oct 29 '18 at 11:16
  • @Ankush i was tried this but my other fragment content is hide below toolbar – Vishal Thakkar Oct 31 '18 at 12:27
5

The best solution that I found to easily collapse, lock it(keep it in collapsed mode) and unlock the collapsingToolbar.

private void collapseAppBar() {
    // Collapse the AppBarLayout with animation
    mAppBarLayout.setExpanded(false, true);
}

private void lockAppBar() {
    /* Disable the nestedScrolling to disable expanding the
     appBar with dragging the nestedScrollView below it */
    ViewCompat.setNestedScrollingEnabled(nestedScrollView, false);

    /* But still appBar is expandable with dragging the appBar itself
    and below code disables that too
     */
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
    behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
        @Override
        public boolean canDrag(AppBarLayout appBarLayout) {
            return false;
        }
    });
}

private void unLockAppBar() {
    ViewCompat.setNestedScrollingEnabled(nestedScrollView, true);

    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
    if (behavior != null) {
        behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
            @Override
            public boolean canDrag(AppBarLayout appBarLayout) {
                return true;
            }
        });
    }
}

And I use these functions in this way:

    Fragment fragment = null;
    Class fragmentClass;
    switch (menuItem.getItemId()) {
        case R.id.fragment1:
            unLockAppBar();
            fragmentClass = first_Fragment.class;
            break;
        case R.id.fragment2:
            collapseAppBar();
            lockAppBar();
            fragmentClass = second_Fragment.class;
            break;
        case R.id.fragment3:
            collapseAppBar();
            lockAppBar();
            fragmentClass = third_Fragment.class;
            break;
Habib Kazemi
  • 2,172
  • 1
  • 24
  • 30
4

You can easily get the Toolbar from your Fragment and then modify or change some property of that Toolbar inside the Fragment.

To get the Toolbar from your Activity you might consider using this.

Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);

Now you need to make the changes on the Toolbar in the onResume function and then undo the changes each time you return from the Fragment inside onStop function. Otherwise the changes made in the Fragment will be carried on to other fragments as well when switched to other Fragment from the navigation drawer.

But in your case, I would recommend each Fragment should have their Toolbar so that it doesn't conflict with each other and can be modified as you need. And yes, remove the Toolbar from your Activity.

So add the Toolbar in the layout of your Fragment like this.

<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="wrap_content"
    android:background="?attr/colorPrimaryDark"/>

Then find it in the Fragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment, container, false);
    Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);

    // Modify your Toolbar here. 
    // ... 
    // For example. 
    // toolbar.setBackground(R.color.red);

    // Create home button
    AppCompatActivity activity = (AppCompatActivity) getActivity();
    activity.setSupportActionBar(toolbar);
    activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

And Override the onOptionsItemSelected function.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()){
        case android.R.id.home:
            getActivity().onBackPressed();
    }
    return super.onOptionsItemSelected(item);
}
Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
  • Thanks for your answer, but how can i make a normale toolbar to a collapsing toolbar programmatically ? – Mayr Technologies Jun 23 '17 at 15:41
  • 1
    I think this is what you're looking for. https://stackoverflow.com/a/30747281/3145960 - Please accept and upvote the answer if that helped. – Reaz Murshed Jun 23 '17 at 16:34
  • This solution doesn't account for the fact that you have to set the toolbar in the `ActionBarDrawerToggle` when you create that object in the `Activity`, which is an important part to make the navigation drawer open when the user clicks on the hamburger icon. – Franco Oct 23 '17 at 00:36
1

I'm using Jetpack's Navigation components with single Activity and different Fragments in my app.

Some Fragments are accessible from bottom navigation (and have Toolbar from Activity). Some others are "special" Fragments and have their own Collapsible Toolbar.

To achieve this, I'm hiding Toolbar from Activity in "special" Fragments with this code in Activity:

// Handle toolbar changes in different Fragments
val navController = findNavController(R.id.nav_host_fragment)
navController.addOnDestinationChangedListener { _, destination, _ ->
    when (destination.id) {
        R.id.my_special_fragment_with_collapsible_toolbar -> {
            binding.toolbarMain.visibility = View.GONE
        }
        else -> {
            binding.toolbarMain.visibility = View.VISIBLE
        }
    }
}
Micer
  • 8,731
  • 3
  • 79
  • 73
1

The recommend practice is to use toolbars in fragments instead of a common toolbar in activity. That way you can control the looks and behaviour of toolbar in fragment. Refer https://developer.android.com/guide/navigation/navigation-ui#support_app_bar_variations

Vasudev
  • 1,936
  • 19
  • 17