Recently I had some fun with CollapsingToolbarLayout, and I learned a few tricks that I would love to share. When using this piece of magic it is very easy to implement material behaviour, your App looks amazing with very little effort. However you might find that you want something slightly different sometimes, and find yourself stuck googling for a solution, or digging into the code.
This happened to me because I wanted to be able to lock the CollapsingToolbarLayout, meaning that I wanted to prevent the user from expanding and collapsing the toolbar by dragging his finger. However I still needed the collapsing behaviour to work programmatically. Took me longer than expected to figure this out, however the solution turned out to be pretty easy, this is the result
You can download or clone the demo project from GitHub
The trick is a good understanding of CoordinatorLayout and Behavior, these are the two components responsible for the magic happening when using CollapsingToolbarLayout, in fact you always need a CoordinatorLayout when doing this. There is nothing really interesting going on in the xml layout, all the magic happens through code. I created a custom Behavior for the AppBarLayout, which does two things, it blocks drag events on the toolbar and it prevents the AppBarLayout from reacting to nested scroll events. Nested scroll events are fired by the NestedScrollView that holds my content, in this case two checkboxes and one button, when scroll events are triggered by the NestedScrollView they get dispatched to the top level CoordinatorLayout which then orchestrates the whole material magic by asking every view for their behavior and acting accordingly. Every view inside a CoordinatorLayout can provide a behavior and this encodes how that view will react to scroll events.
The custom Behavior that I used for AppBarLayout looks like this
Two things are happening here, drag interactions from the toolbar can be blocked and nested scroll events can be refused.
Prevent the user from dragging the toolbar to expand or collapse the AppBarLayout
To block user interactions when the toolbar is dragged I set a drag callback which returns the enabled state of the interaction, this state can be set programmatically so it is possible to enable and disable user interactions via code. The system will use this call to determine whether or not to accept drag events.
Prevent the user from scrolling the content to expand or collapse the AppBarLayout
This is achieved by accepting or refusing nested scroll events, the
onStartNestedScroll() method does exactly that, it also uses a flag that can be set programmatically. When CoordinatorLayout will ask AppBarLayout how it wants to deal with nested scroll events we will simply say that it does or it does not, depending on the flag, and CoordinatorLayout will stop further dispatching of callbacks related to nested scroll events.
Setting the new Behavior for AppBarLayout
With the Behavior in place I just had to actually use it
That’s pretty much it, I hope this was useful and please let me know in the comments!