android - 以编程方式滑动时更改 ViewPager2 滚动速度
问题描述
我知道有办法改变ViewPager
程序幻灯片的动画持续时间(这里)。
但它不工作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)
那么我们如何才能实现这个功能呢?
解决方案
基于这个 issue 票, Android 团队不打算为 ViewPager2 支持这种行为,票中的建议是使用ViewPager2.fakeDragBy()
. 这种方法的缺点是您必须以像素为单位提供页面宽度,尽管如果您的页面宽度与 ViewPager 的宽度相同,那么您可以使用该值来代替。
这是示例实现
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()
}
为了支持RTL
你必须翻转提供给的值ViewPager2.fakeDragBy()
,所以从上面的例子中,而不是在fakeDragBy(-currentPxToDrag)
使用fakeDragBy(currentPxToDrag)
时使用RTL
。
根据官方文档,使用它时要记住的几件事:
负值向前滚动,正向后滚动(用 RTL 翻转)
在调用
fakeDragBy()
使用之前beginFakeDrag()
和完成之后endFakeDrag()
- 这个 API 可以很容易地与
onPageScrollStateChanged
from一起使用,你可以通过方法ViewPager2.OnPageChangeCallback
区分编程拖动和用户拖动isFakeDragging()
- 如果给定的项目是正确的,上面的示例实现没有安全检查。还可以考虑为 UI 的生命周期添加取消功能,这可以通过 RxJava 轻松实现。
推荐阅读
- c# - ASP.NET MVC - 在同一个引导模式弹出窗口中动态加载多个部分视图
- laravel - 运行命令 [$ ./vendor/bin/phpunit --coverage-html coverage] 失败
- python - ModuleNotFoundError python:没有名为“project.utils”的模块
- azure - 是否可以在守护进程中使用 Azure 用户凭据?
- r - 如何使用循环将多个 .txt 文件导入 r 进行文本分析
- javascript - 当我在用户单击后动态添加 hr 标签时,锚点 href 不起作用
- node.js - 如何在执行 ng serve 时从 Angular 应用程序调用外部 API
- ethereum - 交易在 etherscan.io 上显示,但在 API.etherscan 上没有显示
- sql - 在 Join 子句上使用 UDTF
- authentication - laravel 8 中不存在目标类 [auth]