This is the third part of the dribbble Replicating series. The previous post described implementing the animated Action Pane. This part will be about the collapsing header.
Collapsing header reacts to scrolling down the song list, and shrinks when we swipe down to make more space for the content. So its status is tied to that of the song list, and we will store some of the song list states, and pass it to the header.
We remember the value returned by the calculation if the key is equal to the previous composition, otherwise produce and remember a new value by calling topInset
.
The class of the state itself:
To determine the time to reduce the header size, we need to catch the scrolling events and pass them on at the correct moments. To do this we've written a Modifier
extension - we use NestedScrollConnection
to define the scrolling process and calculate when to resize the header. We use the onPreScroll
override function to calculate the necessary parameters. To get a better idea of what's going on, let’s take a look at the gif again and separate the function into logical chunks.
Storing the real offset and last notified value.
We declare a nested function that updates the value and notifies the listener only if the value has changed.
onPreScroll
override fun is called every time the user starts to scroll. We need to set values to the listener as long as the list offset is less than or equal to the height of the header. To better understand this, take a look at the animation below.
isOffsetInAllowedLimits
variable tells us that the offset is in the right range and we can notify the listener.
isScrollingUpWhenHeaderIsDecreased
is responsible for the moment of scrolling up, when we still have the first element visible. The header should shrink in this case. If we are scrolling up, the header should increase instead.
calculateOffsetAndNotify()
and setCurrentOffsetAndNotify()
are used for calculating the offset and notifying the listener if required.
Combining what we described above, and in case the offset does not fit our conditions, return Offset.Zero
.
Here’s the full version all in one place. And this is an example of using the controller:
Note that we use the controller on the SongList
, because it is the scrolling state of the list that determines the state of the header, as determined in the very beginning of the article.
Once we have recorded and remembered the header state, we resize the header very simply:
This concludes the collapsible header implementation. The fourth and final part will tackle animated transitions. See you there!