如何在 RecyclerView 中捕捉到项目的左侧

use*_*694 2 android android-recyclerview pagersnaphelper

我有带有水平滚动的 recyclerview,默认情况下它会使用 LinearSnapHelper 或 PagerSnapHelper 捕捉到项目的中心。我想捕捉到每个项目的左侧。是否可以?

小智 10

您可以轻松扩展 PagerSnapHelper 以将项目左侧对齐。只有最后一项才需要一个技巧。

我的解决方案是:

class AlignLeftPagerSnapHelper : PagerSnapHelper() {
    private var horizontalHelper: OrientationHelper? = null

    override fun findSnapView(layoutManager: RecyclerView.LayoutManager?): View? {
        return getStartView(layoutManager as LinearLayoutManager, getHorizontalHelper(layoutManager))
    }

    private fun getStartView(layoutManager: LinearLayoutManager, helper: OrientationHelper): View? {
        val firstVisibleChildPosition = layoutManager.findFirstVisibleItemPosition()
        val lastCompletelyVisibleChildPosition = layoutManager.findLastCompletelyVisibleItemPosition()
        val lastChildPosition = layoutManager.itemCount - 1

        if (firstVisibleChildPosition != RecyclerView.NO_POSITION) {
            var childView = layoutManager.findViewByPosition(firstVisibleChildPosition)
            if (helper.getDecoratedEnd(childView) < helper.getDecoratedMeasurement(childView) / 2) {
                childView = layoutManager.findViewByPosition(firstVisibleChildPosition + 1)
            } else if (lastCompletelyVisibleChildPosition == lastChildPosition) {
                childView = layoutManager.findViewByPosition(lastChildPosition)
            }
            return childView
        }
        return null
    }

    override fun calculateDistanceToFinalSnap(layoutManager: RecyclerView.LayoutManager, targetView: View): IntArray =
        intArrayOf(distanceToStart(targetView, getHorizontalHelper(layoutManager)), 0)

    override fun findTargetSnapPosition(
        layoutManager: RecyclerView.LayoutManager,
        velocityX: Int,
        velocityY: Int
    ): Int {
        val currentView = findSnapView(layoutManager) ?: return RecyclerView.NO_POSITION
        val currentPosition = layoutManager.getPosition(currentView)

        return if (velocityX < 0) {
            (currentPosition - 1).coerceAtLeast(0)
        } else {
            (currentPosition + 1).coerceAtMost(layoutManager.itemCount - 1)
        }
    }

    private fun distanceToStart(targetView: View, helper: OrientationHelper): Int =
        helper.getDecoratedStart(targetView) - helper.startAfterPadding

    private fun getHorizontalHelper(layoutManager: RecyclerView.LayoutManager): OrientationHelper {
        if (horizontalHelper == null) {
            horizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager)
        }
        return horizontalHelper!!
    }
}
Run Code Online (Sandbox Code Playgroud)