Scrolling a header above a RecyclerView with MotionLayout

Alexandru Gabor
The Halcyon Mobile Collection
2 min readAug 19, 2019
Left: Scroll without MotionLayout. Right: Scroll with MotionLayout

It usually happens that we as Android developers have to implement a screen that consists of some header and a list. With ConstraintLayout that’s pretty easy. Some TextViews, some ImageViews, a RecyclerView, add a few constraints and Bam! the screen is ready.

Except… The header doesn’t scroll, only the items in the RecyclerView.

Your header may be as complex as you want, but for the sake of simplicity it will be only an ImageView in this example.

Potential solutions

At this point you might be tempted to put everything in a NestedScrollView, but this solution has a hidden flaw. The RecyclerView will expand to its maximum height outside the screen and it will practically loose its recycling behavior.

Another solution would be to include the header in the RecyclerView, but this over complicates things since the adapter needs to be notified of any change you might want to do to the header. Also it might turn a simple adapter into one that has to support multiple item types.

MotionLayout

The solution that I find to be the most convenient is to use MotionLayout. MotionLayout is a subclass of ConstraintLayout that will be included in the upcoming 2.0.0 version of ConstraintLayout.

To implement the desired scrolling behavior, the first thing you need to do is replace ConstraintLayout with MotionLayout and then specify a scene file.

The starting state is what was initially in the layout file. So that’s easy, just copy and paste the attributes of the header in the scene file.

For the end state, you need to change the constraints of the header so that instead of its top being constrained to the top of the parent, now its bottom is constrained to top of the parent so that it will go out of the screen.

Now for the transition, we want it to happen on swipe when dragging up. The default behavior of MotionLayout is to end in its closest state. In this case, we want to change it so that it may stop in an intermediary state if needed.

And that’s it.

MotionLayout is capable of more than simulating the behavior of the other solutions. See Google’s examples on GitHub and on Medium

Note that MotionLayout is still in beta, but you can keep an eye on updates here and leave feedback on the issue tracker.

Alexandru Gabor is an Android developer at Halcyon Mobile, a full-service mobile app design and development agency that creates award-winning mobile products for bold startups and brands.

--

--