class CenterZoomLayoutManager : LinearLayoutManager { private var mShrinkAmount = 0.1f private val mShrinkDistance = 0.9f constructor(context: Context?, orientation: Int, reverseLayout: Boolean, shrinkAmount: Float) : super( context, orientation, reverseLayout ) { mShrinkAmount = shrinkAmount } override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams { return RecyclerView.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT ) } override fun canScrollHorizontally(): Boolean { return true } override fun scrollHorizontallyBy(dx: Int, recycler: Recycler, state: RecyclerView.State): Int { val orientation = orientation return if (orientation == HORIZONTAL) { val scrolled = super.scrollHorizontallyBy(dx, recycler, state) val midpoint = width / 2f val d0 = 0f val d1 = mShrinkDistance * midpoint val s0 = 1f val s1 = 1f - mShrinkAmount for (i in 0 until childCount) { val child = getChildAt(i) val childMidpoint = (getDecoratedRight(child!!) + getDecoratedLeft( child )) / 2f val d = min(d1, abs(midpoint - childMidpoint)) val scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0) child.scaleX = scale child.scaleY = scale } scrolled } else { 0 } } override fun smoothScrollToPosition( recyclerView: RecyclerView, state: RecyclerView.State, position: Int ) { val linearSmoothScroller: LinearSmoothScroller = object : LinearSmoothScroller(recyclerView.context) { override fun computeScrollVectorForPosition(targetPosition: Int): PointF? { // Calculate the scroll vector for the target position return super.computeScrollVectorForPosition(targetPosition) } override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float { // Calculate the speed at which the RecyclerView should scroll return 0.1f / displayMetrics.densityDpi } } linearSmoothScroller.targetPosition = position startSmoothScroll(linearSmoothScroller) } }