Written by Damian Petla
Android Developer
Published July 12, 2019

Creating sticky item in RecyclerView – fullscreen and interactive

Sometimes you need to make a sticky item in RecyclerView. Sounds easy, right? But recently I faced a challenge while working on a ad-related implementation – with a need to create fullscreen and interactive one for the new ad position on the front page of the app.


Note: this article was previously published on Damian’s Medium.com profile. The author agreed to republish the article on the Schibsted Developers Blog.

https://github.com/damianpetla/FullscreenExample

Constraints

class AdItemHolder(item: View) : BaseHolder(item) {

    private val adLabel = item.findViewById(R.id.adlabel)
    private val adContent = item.findViewById(R.id.adcontent)
    private val labelElevation = item.resources.getDimension(R.dimen.cardview_default_elevation)

    init {
        item.viewTreeObserver.addOnScrollChangedListener {
            val offset = -item.top.toFloat()
            adLabel.translationY = Math.max(offset, 0f)
            adLabel.translationZ = if (offset < 0) labelElevation else 0f
            adContent.translationY = offset
        }
    }
}

Step by step

private val adLabel = item.findViewById(R.id.adlabel) 
private val adContent = item.findViewById(R.id.adcontent)
item.viewTreeObserver.addOnScrollChangedListener { ... }
val offset = -item.top.toFloat()
adLabel.translationY = Math.max(offset, 0f)
adContent.translationY = offset

Ad content

Ad label

The label’s Y position is updated with Math.max. That way the label sticks when an item goes out of the top edge but moves along when an item is going down.

Label elevation

Modifying translationZ of the label’s view is not something I needed at work but I found it useful working on this post. It feels a bit nicer with respect to Material Design.

adLabel.translationZ = if (offset < 0) labelElevation else 0f

Clickable content

It is worth mentioning that it wasn’t my first approach to the problem. Initially, I tried to place the ad content under RecyclerView and then add a transparent item. However, it was creating some issues and one of them was the fact that RecyclerView was consuming all the click events on our ad. Who needs an ad without being able to click on it, right? ¯\_(ツ)_/¯

Kudos to my colleague Maciej for proofing this approach on iOS.

Summary

This is not rocket science but sometimes the simplest solution requires significant effort to get there. I hope it will be useful to someone else and allow to save a little bit of time. Happy coding!

Written by Damian Petla
Android Developer
Published July 12, 2019