Better smoothScrollToPosition()

A common UX pattern is to tap the top bar and scroll to the top. Easy enough, right? Not so fast. Take for example a RecyclerView with 200 items, scrolled down to position 82. In the first example smoothScrollToPosition makes you watch all these items fly by, increasing in duration the further you scrolled down - just imagine if you scrolled 1,000 items! betterSmoothScrollToPosition short circuits this leading to a consistent scroll every time.

 
smoothScrollToPosition
betterSmoothScrollToPosition
 

Here is a neat little Extension Function to handle this.

fun RecyclerView.betterSmoothScrollToPosition(targetItem: Int) {
    layoutManager?.apply {
        val maxScroll = 10
        when (this) {
            is LinearLayoutManager -> {
                val topItem = findFirstVisibleItemPosition()
                val distance = topItem - targetItem
                val anchorItem = when {
                    distance > maxScroll -> targetItem + maxScroll
                    distance < -maxScroll -> targetItem - maxScroll
                    else -> topItem
                }
                if (anchorItem != topItem) scrollToPosition(anchorItem)
                post {
                    smoothScrollToPosition(targetItem)
                }
            }
            else -> smoothScrollToPosition(targetItem)
        }
    }
}

In a nutshell, it immediately jumps to 10 rows away from the top, then it smooth scrolls. 10 is an arbitrary number but it keeps the example simple and works in many cases. You could always calculate a more appropriate number if you wanted to be more precise. Try it out and let me know what you think!