Recyclerview withy LinearSnapHelper - 从屏幕释放手指时捕捉到下一个项目

时间:2018-02-23 08:31:02

标签: android android-recyclerview

我已按照this Stack Overflow post创建了一个包含viewpager行为的recyclerview。

工作正常,但是当用户抬起屏幕的手指时,我需要触发滚动到下一个项目。现在只有在50%可见时才会捕捉到下一个项目。

更新解决方案

Crysxd的回应是关键。为了检测捕捉方向,我将此代码添加到findTargetSnapPosition函数的顶部:

if (velocityY < 0)
        snapToPrevious = true
else
        snapToNext = true

1 个答案:

答案 0 :(得分:1)

无法围绕自定义SnapHelper。这是一个您可以复制到项目中的类。

解决方案

class ControllableSnapHelper(val onSnapped: ((Int) -> Unit)? = null) : LinearSnapHelper() {
    var snappedPosition = 0
    private var snapToNext = false
    private var snapToPrevious = false
    var recyclerView: RecyclerView? = null

    override fun attachToRecyclerView(recyclerView: RecyclerView?) {
        super.attachToRecyclerView(recyclerView)
        this.recyclerView = recyclerView
    }

    override fun findTargetSnapPosition(layoutManager: RecyclerView.LayoutManager, velocityX: Int, velocityY: Int): Int {
        if (snapToNext) {
            snapToNext = false
            snappedPosition = Math.min(recyclerView?.adapter?.itemCount ?: 0, snappedPosition + 1)
        } else if (snapToPrevious) {
            snapToPrevious = false
            snappedPosition = Math.max(0, snappedPosition - 1)
        } else {
            snappedPosition = super.findTargetSnapPosition(layoutManager, velocityX, velocityY)
        }

        onSnapped?.invoke(snappedPosition)
        return snappedPosition
    }

    fun snapToNext() {
        snapToNext = true
        onFling(Int.MAX_VALUE, Int.MAX_VALUE)
    }

    fun snapToPrevious() {
        snapToPrevious = true
        onFling(Int.MAX_VALUE, Int.MAX_VALUE)
    }
}

您也可以将LinearSnapHelper替换为PagerSnapHelper。只需致电snapToNext()snapToPrevious()。我还实现了在构造函数中传递的回调。

工作原理

我们只是覆盖findTargetSnapPosition(...)方法。此方法可以返回任何位置,然后SnapHelper实现将计算滚动动画以到达该位置。函数snapToNext()snapToPrevious()只是设置了一个布尔值,告诉我们下次调用findTargetSnapPosition(...)时捕捉到下一个或上一个视图。添加snapTo(index: Int)函数也非常简单。设置布尔值后,我们需要启动快照进度。为此,我们调用onFling(...),当用户移动RecyclerView时会调用它。我们需要传递一个超过SnapHelper设置的最小速度的值,因此我们只使用Int.MAX_VALUE。由于我们从不称之为super.findTargetSnapPosition(...),因此PagerSnapHelper使用的实际速度并不重要。