Mayr Technologies
Mayr Technologies

Reputation: 755

Collapsing Toolbar only for one Fragment in Navigation View

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 ?

Upvotes: 13

Views: 7567

Answers (5)

Vasudev
Vasudev

Reputation: 1996

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

Upvotes: 1

Micer
Micer

Reputation: 8979

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

Upvotes: 1

Habib Kazemi
Habib Kazemi

Reputation: 2190

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;

Upvotes: 5

Ankush
Ankush

Reputation: 1978

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

Upvotes: 11

Reaz Murshed
Reaz Murshed

Reputation: 24231

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

Upvotes: 4

Related Questions