自定义布局管理器滚动/动画

Pun*_*uni 1 android carousel android-layout kotlin

我正在尝试做的事情。

使用RecyclerView创建一个简单的轮播。

问题

  1. 最初视图没有对齐中心,视图没有得到我想要的样式。(即,完全可见的项目应该比其他项目大,当手指滚动时它工作正常)
  2. 当以编程方式滚动时,视图不会像用手指滚动时那样获得对齐效果。

例如,请参见下面的附加gif

在此处输入图片说明

  1. 如何在开始时按预期拥有样式(即完全可见的项目更大)。
  2. 单击滚动到按钮时如何获取样式。(它滚动到正确的位置,唯一的问题是没有按预期获得样式并且没有对齐到中心)

完整代码在github 上

这是自定义LayoutManager的代码

open class CarouselLayoutManager(
    context: Context,
    orientation: Int,
    reverseLayout: Boolean
) : LinearLayoutManager(context, orientation, reverseLayout) {

private val mShrinkAmount = 0.15f
private val mShrinkDistance = 0.9f

override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
    scrollVerticallyBy(0, recycler, state)
    super.onLayoutChildren(recycler, state)
}

override fun scrollHorizontallyBy(dx: Int, recycler: RecyclerView.Recycler?, state: RecyclerView.State?): Int {
    val orientation = orientation
    if (orientation == LinearLayoutManager.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 = Math.min(d1, Math.abs(midpoint - childMidpoint))
            val scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0)
            child.scaleX = scale
            child.scaleY = scale
        }
        return scrolled
    } else {
        return 0
    }
}

override fun scrollVerticallyBy(dy: Int, recycler: RecyclerView.Recycler?, state: RecyclerView.State?): Int {
    val orientation = orientation
    if (orientation == LinearLayoutManager.VERTICAL) {
        val scrolled = super.scrollVerticallyBy(dy, recycler, state)
        val midpoint = height / 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 = (getDecoratedBottom(child) + getDecoratedTop(child)) / 2f
            val d = Math.min(d1, Math.abs(midpoint - childMidpoint))
            val scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0)
            child.scaleX = scale
            child.scaleY = scale
        }
        return scrolled
    } else {
        return 0
    }
}
Run Code Online (Sandbox Code Playgroud)

}