Change ViewPager2 Scroll Speed when sliding programmatically

前端 未结 2 1824
我寻月下人不归
我寻月下人不归 2021-02-19 04:10

I know there is way to change animation duration of ViewPager programmatical slide (here).

But its not working on ViewPager2

I tried t

2条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-19 05:02

    Based on this issue ticket Android team is not planning to support such behavior for ViewPager2, advise from the ticket is to use ViewPager2.fakeDragBy(). Disadvantage of this method is that you have to supply page width in pixels, although if your page width is the same as ViewPager's width then you can use that value instead.

    Here's sample implementation

    fun ViewPager2.setCurrentItem(
        item: Int,
        duration: Long,
        interpolator: TimeInterpolator = AccelerateDecelerateInterpolator(),
        pagePxWidth: Int = width // Default value taken from getWidth() from ViewPager2 view
    ) {
        val pxToDrag: Int = pagePxWidth * (item - currentItem)
        val animator = ValueAnimator.ofInt(0, pxToDrag)
        var previousValue = 0
        animator.addUpdateListener { valueAnimator ->
            val currentValue = valueAnimator.animatedValue as Int
            val currentPxToDrag = (currentValue - previousValue).toFloat()
            fakeDragBy(-currentPxToDrag)
            previousValue = currentValue
        }
        animator.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator?) { beginFakeDrag() }
            override fun onAnimationEnd(animation: Animator?) { endFakeDrag() }
            override fun onAnimationCancel(animation: Animator?) { /* Ignored */ }
            override fun onAnimationRepeat(animation: Animator?) { /* Ignored */ }
        })
        animator.interpolator = interpolator
        animator.duration = duration
        animator.start()
    }
    

    To support RTL you have to flip the value supplied to ViewPager2.fakeDragBy(), so from above example instead of fakeDragBy(-currentPxToDrag) use fakeDragBy(currentPxToDrag) when using RTL.

    Few things to keep in mind when using this, based on official docs:

    • negative values scroll forward, positive backward (flipped with RTL)

    • before calling fakeDragBy() use beginFakeDrag() and after you're finished endFakeDrag()

    • this API can be easily used with onPageScrollStateChanged from ViewPager2.OnPageChangeCallback, where you can distinguish between programmatical drag and user drag thanks to isFakeDragging() method
    • sample implementation from above doesn't have security checks if the given item is correct. Also consider adding cancellation capabilities for UI's lifecycle, it can be easily achieved with RxJava.

提交回复
热议问题