以编程方式滑动时更改ViewPager2滚动速度

时间:2019-08-15 06:55:55

标签: android androidx android-viewpager2

我知道有办法更改ViewPager程序化幻灯片(here)的动画持续时间。

但是它不适用于ViewPager2

我尝试过:

try {
        final Field scrollerField = ViewPager2.class.getDeclaredField("mScroller");
        scrollerField.setAccessible(true);
        final ResizeViewPagerScroller scroller = new ResizeViewPagerScroller(getContext());
        scrollerField.set(mViewPager, scroller);
    } catch (Exception e) {
        e.printStackTrace();
    }

IDE在“ mScroller”上给了我警告:

  

无法解析字段“ mScroller”

如果我们运行此代码,那将无法正常工作,并在下面显示错误信息:

No field mScroller in class Landroidx/viewpager2/widget/ViewPager2; (declaration of 'androidx.viewpager2.widget.ViewPager2' appears in /data/app/{packagename}-RWJhF9Gydojax8zFyFwFXg==/base.apk)

那么我们如何实现此功能?

2 个答案:

答案 0 :(得分:2)

ViewPager2团队真的很难更改滚动速度。如果查看方法setCurrentItemInternal,它们将实例化自己的私有ScrollToPosition(..)对象。以及状态管理代码,因此这将是您必须以某种方式覆盖的方法。

作为这里的一种解决方案:https://issuetracker.google.com/issues/122656759,他们说使用(ViewPager2).fakeDragBy()非常难看。

不是最好的选择,只需等待他们给我们提供一个API来设置持续时间或复制其ViewPager2代码并直接修改其LinearLayoutImpl类。

答案 1 :(得分:2)

基于this issue ticket,Android团队不打算支持ViewPager2的这种行为,因此建议您使用ViewPager2.fakeDragBy()。这种方法的缺点是必须提供以像素为单位的页面宽度,尽管如果页面宽度与ViewPager的宽度相同,则可以改用该值。

这里是示例实现

fun ViewPager2.setCurrentItem(
    item: Int,
    duration: Long,
    interpolator: TimeInterpolator = AccelerateDecelerateInterpolator(),
    pagePxWidth: Int = width
) {
    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()
}

要支持RTL,您必须翻转提供给ViewPager2.fakeDragBy()的值,因此在上面的示例中,使用fakeDragBy(-currentPxToDrag)时应使用fakeDragBy(currentPxToDrag)而不是RTL。 / p>

基于official docs,使用此功能时要牢记的几点:

  • 负值向前滚动,正值向后滚动(使用RTL翻转)

  • 在调用fakeDragBy()之前使用beginFakeDrag(),并在完成endFakeDrag()之后

  • 此API可以与onPageScrollStateChanged中的ViewPager2.OnPageChangeCallback一起轻松使用,借助isFakeDragging()方法,您可以在程序化拖动和用户拖动之间进行区分
  • 如果给定的项目正确,则上面的
  • 示例实现没有安全检查。还可以考虑为UI的生命周期添加取消功能,这可以通过RxJava轻松实现。
相关问题