You must disable the extension on CollapsingToolbarLayout for specific fragments

I have an AppCompatActivity that controls the replacement of many fragments. Here is my layout for it.

activity_main.xml

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_height="match_parent" android:layout_width="match_parent" android:fitsSystemWindows="true"> <include layout="@layout/activity_main_frame"/> <android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" android:background="@color/white" app:headerLayout="@layout/drawer_header" app:menu="@menu/drawer"/> </android.support.v4.widget.DrawerLayout> 

activity_main_frame.xml

 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:fitsSystemWindows="true"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_scrollFlags="scroll|exitUntilCollapsed" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginStart="48dp" app:expandedTitleMarginEnd="64dp"> <ImageView android:id="@+id/backdrop" android:layout_width="match_parent" android:layout_height="256dp" android:scaleType="centerCrop" android:fitsSystemWindows="true" app:layout_collapseMode="parallax" /> <include layout="@layout/activity_main_items"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin"/> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone" android:layout_gravity="bottom"/> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" > </FrameLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab1" android:layout_height="wrap_content" android:layout_width="wrap_content" app:layout_anchor="@id/appbar" app:layout_anchorGravity="bottom|right|end" app:borderWidth="0dp" android:src="@drawable/app_ic_slide_wallpaper_dark" android:layout_margin="@dimen/big_padding" android:clickable="true"/> </android.support.design.widget.CoordinatorLayout> 

My home fragment is initially installed, and it is there that I want the panel to collapse the panel to expand, and this works fine. However, when I change fragments from the side drawer, I want to disable the expanding toolbar.

I figured out how to collapse it when a box item is selected, but I also need to make sure that it does not expand if the home fragment is not displayed. is it possible?

 public void collapseToolbar(){ CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbar.getLayoutParams(); behavior = (AppBarLayout.Behavior) params.getBehavior(); if(behavior!=null) { behavior.onNestedFling(coordinator, appbar, null, 0, 10000, true); } } 
+44
android android-support-library android-toolbar coordinator-layout
Jun 11 '15 at 11:09
source share
12 answers

Now, in the v23 support library, you can easily control the visibility of your panel.

Just get a link to your AppBarLayout and hide / show it depending on the fragment you want to download:

 private AppBarLayout appBarLayout; @Override protected void onCreate(Bundle savedInstanceState) { [...] appBarLayout = (AppBarLayout) findViewById(R.id.appbar); [...] } public void switchToFragment(Fragment fragment, String tag, boolean expandToolbar){ FragmentManager fragmentManager = getSupportFragmentManager(); Fragment currentFragment = fragmentManager.findFragmentByTag(currentFragmentTag); if(currentFragment == null || !TextUtils.equals(tag, currentFragmentTag) ){ currentFragmentTag = tag; fragmentManager .beginTransaction() .replace(R.id.flContent, fragment, currentFragmentTag) .commit(); if(expandToolbar){ appBarLayout.setExpanded(true,true); }else{ appBarLayout.setExpanded(false,true); } } } 

PS do not forget to add the necessary dependencies to your build.gradle:

 dependencies { compile 'com.android.support:design:23.2.1' compile 'com.android.support:appcompat-v7:23.2.1' compile 'com.android.support:recyclerview-v7:23.2.1' } 

EDIT: If you also want to lock the toolbar in certain fragments (except for collapsing), you will have to resort to workarounds, since this function is not provided by CollapsingToolbarLayout so far (v23.2.1 support design). Here you can find the proposed solution.

+14
Oct. 13 '15 at 11:55
source share

Disable nested scrolling of the contents of the scrollable fragment:

 recyclerView.setNestedScrollingEnabled(false); 

Use this if you are using the support library:

 ViewCompat.setNestedScrollingEnabled(recyclerView, false); 
+48
Aug 09 '15 at 17:21
source share

This class will allow you to disable / re-enable extension behavior.

 public class DisableableAppBarLayoutBehavior extends AppBarLayout.Behavior { private boolean mEnabled; public DisableableAppBarLayoutBehavior() { super(); } public DisableableAppBarLayoutBehavior(Context context, AttributeSet attrs) { super(context, attrs); } public void setEnabled(boolean enabled) { mEnabled = enabled; } @Override public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) { return mEnabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes); } public boolean isEnabled() { return mEnabled; } } 

Use it in your layout like this:

 <android.support.design.widget.AppBarLayout ... other attributes ... app:layout_behavior="com.yourpackage.DisableableAppBarLayoutBehavior" > <!-- your app bar contents --> </android.support.design.widget.AppBarLayout> 

Then, if you want to disable the behavior:

 AppBarLayout myAppBar = ....; CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) myAppBar.getLayoutParams(); ((DisableableAppBarLayoutBehavior) layoutParams.getBehavior()).setEnabled(false); 
+29
Aug 18 '16 at 19:15
source share

All you have to do is replace the CoordinatorLayout with a custom CoordinatorLayout implementation that will spoof this nested scroll.

Implementation of MyCoordinatorLayout:

 public class MyCoordinatorLayout extends CoordinatorLayout { private boolean allowForScroll = false; public MyCoordinatorLayout(Context context) { super(context); } public MyCoordinatorLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { return allowForScroll && super.onStartNestedScroll(child, target, nestedScrollAxes); } public boolean isAllowForScroll() { return allowForScroll; } public void setAllowForScroll(boolean allowForScroll) { this.allowForScroll = allowForScroll; } } 

activity type xml:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <android.support.v4.widget.DrawerLayout android:id="@+id/drawerLayout" android:layout_width="match_parent" android:layout_height="match_parent" > <!--CONTENT--> <com.example.views.MyCoordinatorLayout android:id="@+id/coordinator" 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" android:fitsSystemWindows="true" > <com.example.views.ControllableAppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="192dp" android:fitsSystemWindows="true" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginBottom="32dp" app:expandedTitleMarginEnd="64dp" app:expandedTitleMarginStart="48dp" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:id="@+id/header" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/primary" android:fitsSystemWindows="true" android:scaleType="centerCrop" app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </android.support.design.widget.CollapsingToolbarLayout> </com.example.views.ControllableAppBarLayout> <FrameLayout android:id="@+id/flContent" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </com.example.views.MyCoordinatorLayout> <!-- DRAWER --> <fragment android:id="@+id/fDrawer" android:name="com.example.fragment.DrawerFragment" android:layout_width="@dimen/drawer_width" android:layout_height="match_parent" android:layout_gravity="left|start" android:fitsSystemWindows="true" android:clickable="true" /> </android.support.v4.widget.DrawerLayout> </LinearLayout> 

I recommend that you use your own implementation of AppBarLayout using helper methods to collapse / expand the toolbar. On this gist you can find it.

So now is the time to customize our toolbar in action.

 public class ToolbarAppcompatActivity extends AppCompatActivity implements AppBarLayout.OnOffsetChangedListener { protected Toolbar toolbar; protected MyCoordinatorLayout coordinator; protected ControllableAppBarLayout appbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); configureToolbar(); switchFragment(new FooFragment(), "FOO", true); } protected void configureToolbar() { toolbar = (Toolbar) findViewById(R.id.toolbar); coordinator = (MyCoordinatorLayout) findViewById(R.id.coordinator); appbar = (ControllableAppBarLayout) findViewById(R.id.appbar); appbar.addOnOffsetChangedListener(this); getDelegate().setSupportActionBar(toolbar); } public void switchToFragment(Fragment fragment, String tag, boolean expandToolbar){ FragmentManager fragmentManager = getSupportFragmentManager(); Fragment currentFragment = fragmentManager.findFragmentByTag(currentFragmentTag); if(currentFragment == null || !TextUtils.equals(tag, currentFragmentTag) ){ currentFragmentTag = tag; fragmentManager .beginTransaction() .replace(R.id.flContent, fragment, currentFragmentTag) .commit(); if(expandToolbar){ expandToolbar(); }else{ collapseToolbar(); } } } protected void addFragment(Fragment fragment, String tag, boolean expandToolbar) { FragmentManager fragmentManager = getSupportFragmentManager(); currentFragmentTag = tag; fragmentManager .beginTransaction() .add(R.id.flContent, fragment, currentFragmentTag) .addToBackStack(tag) .commit(); if(expandToolbar){ expandToolbar(); }else{ collapseToolbar(); } } protected void collapseToolbar(){ appbar.collapseToolbar(); coordinator.setAllowForScroll(false); } public void expandToolbar(){ appbar.expandToolbar(); coordinator.setAllowForScroll(true); } } 

Each time you just want to switch the toolbar and minimize / expand the call to the switchFragment / addFragment method with the corresponding boolean parameter.

Just one last note. Make sure you use the latest support libraries.

 dependencies { // android support compile 'com.android.support:appcompat-v7:22.2.1' compile 'com.android.support:recyclerview-v7:22.2.1' compile 'com.android.support:design:22.2.1' } 

Do not use the include tag in AppBarLayout. This does not work.

+11
Jul 23 '15 at 21:39
source share

In the Android Design library v23.1.1, the method described by @LucyFair does not work. I managed to get it working by setting app:layout_scrollFlags only enterAlwaysCollapsed , and the application panel remains “locked”.

Hope this helps. :)

+4
Feb 09 '16 at 12:27
source share

I found a workaround that works with activity and various fragments. You implement CollapsingToolbarLayout with AppBar etc. In your activity, and then every time you call a new fragment, you can call these 2 functions.

  • When I want my application bar to continue to collapse:

     public void lockAppBarClosed() { mAppBarLayout.setExpanded(false, false); mAppBarLayout.setActivated(false); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbar_height); } 
  • When I want my application bar to expand and scroll again

     public void unlockAppBarOpen() { mAppBarLayout.setExpanded(true, false); mAppBarLayout.setActivated(true); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbar_expand_height); } 



You can call thoses functions from your fragments by implementing an interface. Here is a short example for your case (the toolbar expands only in homeFragment)

 public interface CustomListener() { void unlockAppBarOpen(); void lockAppBarClosed() } public class MainActivity extends BaseActivity implements CustomListener { @Override public void unlockAppBarOpen() { mAppBarLayout.setExpanded(true, false); mAppBarLayout.setActivated(true); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbar_expand_height); } @Override public void lockAppBarClosed() { mAppBarLayout.setExpanded(false, false); mAppBarLayout.setActivated(false); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbar_height); } } public class MainFragment extends BaseFragment { @Override public void onResume() { super.onPause(); ((MainActivity) getContext()).unlockAppBarOpen(); } } public class SecondFragment extends BaseFragment { @Override public void onResume() { super.onPause(); ((MainActivity) getContext()).lockAppBarClosed(); } } 

In this example:

  • every time MainFragment is displayed → it expands the toolbar and makes it expandable and expandable

  • every time a second fragment is displayed → il will minimize the toolbar to a standard size and prevent it from expanding again

Hope this helps you!

+2
Jan 15 '16 at 10:31
source share

I found a simple solution to turn on / off collapse in CollapsingToolbarLayout:

  private void setExpandEnabled(boolean enabled) { mAppBarLayout.setExpanded(enabled, false); mAppBarLayout.setActivated(enabled); final AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); if (enabled) params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); else params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); collapsingToolbarLayout.setLayoutParams(params); } 
+2
Mar 02 '17 at 15:00
source share

I used the @JasonWyatt solution and added a DragCallback to the behavior class to prevent CollapsingToolbarLayout from touching and dragging to expand it

 private void setDragCallback() { setDragCallback(new DragCallback() { @Override public boolean canDrag(@NonNull AppBarLayout appBarLayout) { return mEnabled; } }); } 
+2
Mar 21 '17 at 16:02
source share

I cannot comment, so as an independent answer, I will post my additions to JasonWyatt's DisableableAppBarLayoutBehavior.

 public class DisableableAppBarLayoutBehavior extends AppBarLayout.Behavior { private boolean mEnabled = true; // enabled by default public DisableableAppBarLayoutBehavior() { super(); } public DisableableAppBarLayoutBehavior(Context context, AttributeSet attrs) { super(context, attrs); } public void setEnabled(boolean enabled) { mEnabled = enabled; } @Override public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) { return mEnabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { if (!isEnabled()) return; super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) { if (!isEnabled()) return; super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type); } public boolean isEnabled() { return mEnabled; } } 

In addition to onStartNestedScroll, onNestedPreScroll and onNestedScroll are also blocked to avoid unexpected behavior. For example, in my case, calling setExpanded (false, true) in my application panel slowed down the expected behavior and was still expanding with delays. Now it works:

 LayoutParams layoutParams = (LayoutParams) context.appBarLayout.getLayoutParams(); ((DisableableAppBarLayoutBehavior)layoutParams.getBehavior()).setEnabled(false); context.appBarLayout.setLayoutParams(layoutParams); context.appBarLayout.setExpanded(false, true); // collapse app bar 
+1
Oct 27 '17 at 11:28
source share

None of the solutions provided worked for me, except this one. With this solution, I can easily control the state of the minimized toolbar. This will prevent the collapsing toolbar from expanding and setting a title for it.

 public void lockAppBar(boolean locked,String title) { if(locked){ appBarLayout.setExpanded(false, true); int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics()); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams(); lp.height = px; appBarLayout.setLayoutParams(lp); collapsingToolbarLayout.setTitleEnabled(false); toolbar.setTitle(title); }else{ appBarLayout.setExpanded(true, false); appBarLayout.setActivated(true); CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); lp.height = (int) getResources().getDimension(R.dimen.toolbarExpandHeight); collapsingToolbarLayout.setTitleEnabled(true); collapsingToolbarLayout.setTitle(title); } } 
0
Jun 29 '16 at 5:04 on
source share

You can block the appbarlayout extension by resetting the toolbar height reset to the toolbar height

 toolbarHeight = toolbar.getLayoutParams().height; if (expand) { collapsingToolbar.getLayoutParams().height = getResources().getDimensionPixelOffset(R.dimen.collapsingToolbarDefaultHeight); appBarLayout.setExpanded(true, true); } else { //collapse //** it is important you do this before resetting ** appBarLayout.setExpanded(false, true); appBarLayout.postDelayed(new Runnable() { @Override public void run() { collapsingToolbar.getLayoutParams().height = toolbarHeight; } }, 700/* 600 is default animation time to collapse */); } 
0
Jan 17 '18 at 11:44
source share

Find the AppBarLayout ID like this.

 appBarLayout = (AppBarLayout) findViewById(R.id.appbar); 

Disable deploy to CollapsingToolbarLayout for specific snippets

 appBarLayout.setExpanded(true,true); 

Enable deploy to CollapsingToolbarLayout for specific snippets

 appBarLayout.setExpanded(false,true); 

Hope this helps you!

0
Jan 18 '18 at 10:14
source share



All Articles