RecyclerView.SmoothScroller 自定义平滑滚动的快慢

根据上次的文章:RecyclerView - 实现目标Item滚动到指定位置(SmoothScroller)我们可以使用 SmoothScroller 来实现目标Item滚动到指定位置。

最近实现一个功能,发现SmoothScroller的平滑滚动速度有点快,需求是需要有个明显的平滑滚动过程,所以研究一下如何减缓这个滚动速度。

先熟悉下如何使用,示例:

private fun smoothMoveToPosition(position: Int) {
     val smoothScroller = LinearSmoothScroller(context)
     smoothScroller.targetPosition = position
     rv.layoutManager?.startSmoothScroll(smoothScroller)
}

类 - LinearSmoothScroller,大概意思:

由RecyclerView.SmoothScroller实现,该实现使用LinearInterpolator直到目标位置成为RecyclerView的子级,然后使用DecelerateInterpolator缓慢地接近目标位置。

然后找到了如下这个方法:

    private static final float MILLISECONDS_PER_INCH = 25f;
    /**
     * Calculates the scroll speed.
     *
     * <p>By default, LinearSmoothScroller assumes this method always returns the same value and
     * caches the result of calling it.
     *
     * @param displayMetrics DisplayMetrics to be used for real dimension calculations
     * @return The time (in ms) it should take for each pixel. For instance, if returned value is
     * 2 ms, it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds.
     */
    protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
        return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
    }

计算滚动速度。
默认情况下,LinearSmoothScroller 假定此方法始终返回相同的值并缓存调用它的结果。
参数:
displayMetrics – 用于实际尺寸计算的 DisplayMetrics
返回:
每个像素应该花费的时间(以毫秒为单位)。例如,如果返回值为 2 毫秒,则意味着使用 LinearInterpolation 滚动 1000 个像素需要 2 秒。

所以我们可以尝试去重写该方法: calculateSpeedPerPixel(displayMetrics: DisplayMetrics)

// 每英寸毫秒
val MILLISECONDS_PER_INCH: Float = 1000F
private val smoothScroller by lazy {
    object : LinearSmoothScroller(this) {
        override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
            // 每个像素应该花费的时间(以毫秒为单位)。这里我们自定义MILLISECONDS_PER_INCH值为 1000 毫秒,则意味着使用 LinearInterpolation 滚动 1 个像素需要(MILLISECONDS_PER_INCH / displayMetrics.densityDpi)秒。
            return MILLISECONDS_PER_INCH / displayMetrics.densityDpi
        }
    }
}

完整代码块:

val MILLISECONDS_PER_INCH: Float = 1000F
private val smoothScroller by lazy {
    object : LinearSmoothScroller(this) {
        override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
            // 每个像素应该花费的时间(以毫秒为单位)。这里我们自定义MILLISECONDS_PER_INCH值为 1000 毫秒,则意味着使用 LinearInterpolation 滚动 1 个像素需要(MILLISECONDS_PER_INCH / displayMetrics.densityDpi)秒。
            return MILLISECONDS_PER_INCH / displayMetrics.densityDpi
        }
    }
}  }
}

...

private fun smoothMoveToPosition(position: Int) {
     smoothScroller.targetPosition = position
     rv.layoutManager?.startSmoothScroll(smoothScroller)
}


版权声明:本文为qq_20613731原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。