185

Simple question, but I can't find an answer. How can I collapse or expand the CollapsingToolbarLayout programmatically?

collapsed toolbar

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

expanded toolbar

Mangesh
  • 5,491
  • 5
  • 48
  • 71
Tomas
  • 4,652
  • 6
  • 31
  • 37
  • 1
    I was wondering the same thing. It could also be interesting to expand the toolbar to fullscreen once a user clicks on the embedded layout (eg image). – Moritz Jun 06 '15 at 08:33
  • I was a little lost with the answers which are omitting the fact that `CollapsingToolbarLayout` cannot expand or collapse **itself** what's worst, other comments are making it seemed as if it's an issue that has to do with the version, In reality what you need to handle is its parent, which is funny because `CollapsingToolbarLayout` **CAN** _disable_ its own collapse/expansion, but for some reason it cannot _trigger_ them. – Delark Nov 15 '21 at 17:55

11 Answers11

380

Using Support Library v23, you can call appBarLayout.setExpanded(true/false).

Further reading: AppBarLayout.setExpanded(boolean)

Amitoj
  • 171
  • 2
  • 15
jaxvy
  • 5,040
  • 1
  • 21
  • 22
  • 2
    Ok,thank you for the tip, but support libs v23 are very buggy, so I can't to test it now, because I need to stay on 22.2.1.... – Tomas Sep 02 '15 at 15:59
  • Now you have 23.0.1 with some fixes – Mario Velasco Sep 08 '15 at 08:43
  • 6
    Is it possible to define a custom animation with support libs 23.1.1? setExpanded(boolean, true) hav a really slow animation... – Nifhel Nov 24 '15 at 12:52
  • I had an issue where I have a layout with a collapsible toolbar and an recyclerview under it. When deleting items from the recyclerview the toolbar did not behave appropriately, so i would expand the app bar layout and it worked properly. I ended up using the appBarLayout.setExpanded(true, true) for the animation. – Ray Hunter Mar 24 '16 at 16:58
  • This only partly expands/collapses the `AppBarLayout`. There's also a nested `CoordinatorLayout` to deal with. – IgorGanapolsky Jan 24 '21 at 23:57
48

I use this code for collapsing toolbar. Still cannot find a way to expand it.

public void collapseToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.onNestedFling(rootLayout, appbarLayout, null, 0, 10000, true);
    }
}

Edit 1: The same function with negative velocityY but the toolbar is not expanded 100% and false for last param should work

public void expandToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.onNestedFling(rootLayout, appbarLayout, null, 0, -10000, false);
    }
}

Edit 2: This code do the trick for me

public void expandToolbar(){
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbarLayout.getLayoutParams();
    behavior = (AppBarLayout.Behavior) params.getBehavior();
    if(behavior!=null) {
        behavior.setTopAndBottomOffset(0);
        behavior.onNestedPreScroll(rootLayout, appbarLayout, null, 0, 1, new int[2]);
    }
}
  • setTopAndBottomOffset do expand the toolbar
  • onNestedPreScroll do show the content inside expanded toolbar

Will try to implement Behavior by myself.

  • 2
    Edit 1 will also work if you set the the last parameter of `onNestedFling` to `false`. – Ricky Lee Jun 22 '15 at 09:45
  • 2
    params.getBehavior() is returning null. In xml, layout_behaviour tag is set on sibling NestedScrollView, not the AppBarLayout. Can you help me? – User31689 Jun 26 '15 at 06:53
  • Thank you. Edit 1 work properly, if last param is false. :) – Sirelon Jun 30 '15 at 16:22
  • @GobletSky I faced the same problem. I had NestedScrollView in my fragment and tried to call `onNestedFling` **before** set the fragment. After set the fragment, I could call the method successfully. – usp Jul 17 '15 at 09:55
  • @usp Actually, my problem was entirely different(somewhat noobish mistake). See this: http://stackoverflow.com/questions/31067082/params-getbehaviour-returns-null-value/31182999#31182999 – User31689 Jul 17 '15 at 12:20
  • Working or not, this is more a workaround than a proper solution, you shouldn't rely on the behavior internals to collapse or expand the toolbar. – Marc Plano-Lesay Oct 29 '15 at 06:37
  • Edit 1 and Edit 2 all not work in ```com.android.support:design:27.0.0``` – Better Nov 06 '17 at 09:29
  • Edit 2 onNestedPreScroll is deprecated, from what I saw you need to supply another parameter type but after seeing the source code I didn't get where they used it – Anton Makov Mar 13 '18 at 00:42
34

You can define how much it expands or collapses with your custom animator. Just use the setTopAndBottomOffset(int).

Here is an example:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBar.getLayoutParams();
final AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
if (behavior != null) {
    ValueAnimator valueAnimator = ValueAnimator.ofInt();
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            behavior.setTopAndBottomOffset((Integer) animation.getAnimatedValue());
            appBar.requestLayout();
        }
    });
    valueAnimator.setIntValues(0, -900);
    valueAnimator.setDuration(400);
    valueAnimator.start();
}
Vasily Kabunov
  • 6,511
  • 13
  • 49
  • 53
gerhard
  • 443
  • 4
  • 6
  • 3
    This is the only answer that actually let you animate to a custom offset. Many thanks! – Guilherme Torres Castro Jul 05 '16 at 18:52
  • 3
    appBar.setExpanded(false, true); (open/close, animate) You don't need to write all those lines – Puni Jun 30 '17 at 20:06
  • 2
    to @Puni, if you want to expand / collapse to a "custom" offset (like doing multiple stages collapsing), you'll need this. – Palatis Aug 05 '17 at 23:54
  • 1
    This is the best solution to animate AppBar offset in case u don't want to write custom behavior. The one update to the code snippet is to call valueAnimator.setIntValues() with behavior.topAndBottomOffset start value instead of 0 to start animate from current appbar offset. – reel Oct 20 '19 at 13:22
  • To use a custom variable ```( -900 )``` to set ```valueAnimator.setIntValues``` The beter solution is that to use ```- ( appBar.getTotalScrollRange() )``` – Ali Rezaiyan Apr 06 '20 at 10:06
12

I've written a small extension to AppBarLayout. It allows for expanding and collapsing of the CollapsibleToolbarLayout both with and without animation. It seems to be doing it quite right.

Feel free to try it out.

Just use it instead of your AppBarLayout, and you can call methods responsible for expanding or collapsing of the CollapsingToolbarLayout.

It's working exactly as expected in my project, but you might need to tweak the fling/scroll values in the perform... methods (especially in performExpandingWithAnimation()) to fit perfectly with your CollapsibleToolbarLayout.

Bartek Lipinski
  • 30,698
  • 10
  • 94
  • 132
  • @ssdeno please read the Readme.md of the Github gist. It's deprecated since v23 of the Support library. Since the v23 of Support (proceeding to AndroidX), there is `setExpanded` method in the `AppBarLayout`. – Bartek Lipinski May 15 '19 at 16:11
8

Use mAppBarLayout.setExpanded(true) to expand Toolbar and use mAppBarLayout.setExpanded(false) to collapse Toolbar.

If you want to change CollapsingToolbarLayout height programmatically then just use mAppBarLayout.setLayoutParams(params);

Expand:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
params.height = 3*200; // HEIGHT

mAppBarLayout.setLayoutParams(params);
mAppBarLayout.setExpanded(true);

Collapse:

CoordinatorLayout.LayoutParams params =(CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
params.height = 3*80; // HEIGHT

mAppBarLayout.setLayoutParams(params);
mAppBarLayout.setExpanded(false);
Ferdous Ahamed
  • 21,438
  • 5
  • 52
  • 61
5

for the ones who wants to work with onNestedPreScroll and get error like me. i get NullPointerException in onCreate with out this line

    CoordinatorLayout coordinator =(CoordinatorLayout)findViewById(R.id.tab_maincontent);
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
    //below line
    params.setBehavior(new AppBarLayout.Behavior() {});

and doesn't work properly with this. but i work around this problem with

in onCreate :

        scrollToolbarOnDelay();

and...

    public void scrollToolbarOnDelay() {
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.tab_appbar);
                    CoordinatorLayout coordinator = (CoordinatorLayout) findViewById(R.id.tab_maincontent);
                    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
         if(behavior!=null)
                    behavior.onNestedPreScroll(coordinator, appBarLayout, null, 0, 100, new int[]{0, 0});
         else
            scrollToolbarOnDelay()
                }
            }, 100);


        }
Sepehr Nozaryian
  • 370
  • 4
  • 15
5

Try this...

Expand

appBarLayout.setExpanded(true, true);

To recall

appBarLayout.setExpanded(false, true);
Victor Sam VS
  • 139
  • 3
  • 4
3

To expand/collapse AppBarLayout programmatically:

fun expandAppBarLayout(expand: Boolean, isAnimationEnabled: Boolean){
    appBarLayout.setExpanded(expand, isAnimationEnabled);
}
avisper
  • 878
  • 12
  • 11
1

This may help to expand or collapse :

appBarLayout.setActivated(true);
appBarLayout.setExpanded(true, true);
Firdous nath
  • 1,487
  • 1
  • 14
  • 38
ROHIT LIEN
  • 497
  • 3
  • 8
0

i have using this

 private fun collapseAppbar() {
        scrollView.postDelayed(Runnable {
            scrollView?.smoothScrollTo(50, 50)
        }, 400)
    }
denizs
  • 693
  • 1
  • 7
  • 20
0

Make sure your parent is a coordinator layout, otherwise setExpanded will not work.

Andre Thiele
  • 3,202
  • 3
  • 20
  • 43