业务需求
项目中使用了一个循环的Banner,现在需要在滑动过程中每个Banner元素完成缩放的动画
需求分析
现有的LoopBanner是封装的ViewPager2实现,因此实现滑动过程中的动画效果可以通过setPageTransformer()设置,然而LoopBanner已经封装在线上的aar中,无法直接修改其代码,并且ViewPager2作为其私有成员无法在外部获取,它的子类也无法访问到,但是子类拥有有该成员,所以可以采用反射方法获取到该成员,并通过子类本身获取到该成员实例,然后设置该实例对应的属性
具体实现
- 实现ViewPager2.PageTransformer接口,使ViewPager2的子View切换具有缩放效果
- 参考(ctrl+ c):https://developer.android.google.cn/training/animation/screen-slide-2?hl=zh-cn#zoom-out
private const val MIN_SCALE = 0.85f
//使ViewPager2的子View切换具有缩放效果
private val scalePageTransformer by lazy {
ViewPager2.PageTransformer { page, position ->
page.apply {
val pageWidth = width
val pageHeight = height
when {
position < -1 -> { // [-Infinity,-1)
alpha = 0f
}
position <= 1 -> { // [-1,1]
val scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position))
val vertMargin = pageHeight * (1 - scaleFactor) / 2
val horzMargin = pageWidth * (1 - scaleFactor) / 2
translationX = if (position < 0) {
horzMargin - vertMargin / 2
} else {
horzMargin + vertMargin / 2
}
scaleX = scaleFactor
scaleY = scaleFactor
alpha = 1f
}
else -> { // (1,+Infinity]
alpha = 0f
}
}
}
}
}
- 在子类的初始化中,通过反射获取ViewPager2的实例,并设置其属性
init{
//父类:BannerViewPager
val className = BannerViewPager::class.java.canonicalName!!
val superClass = Class.forName(className)
//父类私有成员变量:mViewPager
val pagerField = superClass.getDeclaredField("mViewPager")
pagerField.isAccessible = true
val pageViewPager2 = pagerField.get(this)
(pageViewPager2 as? ViewPager2)?.setPageTransformer(scalePageTransformer)
}