How to block CollapsingToolbarLayout in place

I had some fun with CollapsingToolbarLayout, and I learned a few tricks that I would love to share. With 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.

I wanted to prevent the user from expanding and collapsing the toolbar by dragging his finger while still keeping the collapsing/expanding 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 allows me to

  • Block drag events on the toolbar
  • Prevent 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. These events bubble their way up to the CoordinatorLayout, which then orchestrates the whole material magic by asking every view for its behaviour and acting accordingly. Every view inside a CoordinatorLayout can provide a behavior and this encodes how that view will react to scroll events.

My custom Behavior for AppBarLayout looks like this

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. The state is set programmatically so it is possible to enable and disable user interactions from the 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

I achieve this by accepting or refusing nested scroll events. The onStartNestedScroll() method does exactly that. This is also driven by a flag which I can set from my code. When CoordinatorLayout asks AppBarLayout how it wants to deal with nested scroll events I simply say that it does or it does not, depending on the flag. If the flag is false 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

Conclusion

I packaged these two functionalities into a controller class that is ready to be used in other projects, so feel free.
Also, I created a demo project on GitHub to demonstrate this in action.

That’s pretty much it, I hope this was useful and please let me know in the comments!

Unique opportunity! Help a fellow grow his blog!

Hi there! If you’ve read this far maybe you think this was useful, or fun, or I don’t know what but for some reason You Got Here! Great! Please consider sharing this post with your network, I am trying to get The Code Butchery to grow so I can provide more content like this, will you help me in my journey? Thank you!

Share this

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.