我知道有办法更改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)
那么我们如何实现此功能?
答案 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()
之后
onPageScrollStateChanged
中的ViewPager2.OnPageChangeCallback
一起轻松使用,借助isFakeDragging()
方法,您可以在程序化拖动和用户拖动之间进行区分