前言
在平常的开发中,咱们往往需要做一些页面、布局相关的切换作用,曾经写过一篇转场相关的动画的文章juejin.cn/post/719956…
但这是比较重量级,有时候咱们做fragment切换或者一些控件切换做联接动画,想要比较便利的完成,其实ViewPager就供给了切换动画的办法,并且运用起来也十分的便利,扩展性还很不错,简略来说便是你能够用简略的办法去完成你自界说的控件切换作用。
1. 运用办法
运用十分简略
viewpager.setPageTransformer(CardPageTransformer())
直接调用viewpager的setPageTransformer办法,传一个PageTransformer,而这个PageTransformer需要咱们自界说,具体完成切换动画作用的地方也是在这儿面
在transformPage办法中写具体的动画作用
2. 部分动画作用
为了便利运用,官方也现已供给一些根底的动画作用给开发者运用
能够参考developer.android.google.cn/develop/ui/…
假如你要完成的作用是在里面的,你能够直接拷贝它的代码来运用,这是最便利的办法。
当然,除了运用官方列举出的一些根底作用之外,你还能够界说自己的作用。咱们能够来看看一个卡片切换的作用,代码便是上面的运用列举的demo
class CardPageTransformer : ViewPager2.PageTransformer {
var mScaleOffset = 200f
var mTranslationOffset = 100f
override fun transformPage(page: View, position: Float) {
if (position <= 0f) {
page.translationX = 0f
} else {
val pageWidth: Int = page.width
val transX = -pageWidth * position + mTranslationOffset * position
page.translationX = transX
val scale: Float = (pageWidth - mScaleOffset * position) / pageWidth.toFloat()
page.scaleX = scale
page.scaleY = scale
page.translationZ = -position
}
}
}
能够看看作用
咱们也能够用别的一种办法更直观的去完成
class DepthPageTransformer : ViewPager2.PageTransformer {
private val MIN_SCALE = 0.75f
override fun transformPage(page: View, position: Float) {
page.apply {
val pageWidth = width
when {
position < -1 -> {
alpha = 0f
}
position <= 0 -> {
alpha = 1f
translationX = 0f
translationZ = 0f
scaleX = 1f
scaleY = 1f
}
position <= 1 -> {
alpha = 1 - position
translationX = pageWidth * -position
translationZ = -1f
val scaleFactor = (MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)))
scaleX = scaleFactor
scaleY = scaleFactor
}
else -> {
alpha = 0f
}
}
}
}
}
看看作用
能够看到两个的作用差不多,但是第二个demo写了if-else判别会比较好理解一点。
2. transformPage办法
上面说了,自界说切换动画作用的办法便是用transformPage,该办法有两个参数,View类型的page和Float类型的position
上面的第二个Demo能够看出,它是依据position的4个不同的区间做操作。那么这个pager是什么,position又是什么呢?
咱们能够去看接口的阐明
嗯~ 看完之后仍是有点懵,没事,咱们能够写个空的PageTransformer然后加打印看看这个切换的进程
class EmptyPageTransformer : ViewPager2.PageTransformer {
override fun transformPage(page: View, position: Float) {
Log.v("mmp","==== ${page.tag} ${position}")
}
}
PS:我给每个view设置了不同的tag,便利打印
从页面1切换到页面2的进程能够看到
其实看这个打印是不是现已很明显了,你能看到这个进程有两个view都有回调到这个办法,一眼你就能理解是切换的两个view吗,而tag为0的view的position是从0到-1,tag为1的view的position是从1到1。
那从这儿你就能很明显的得到这些信息,这个进程涉及两个控件,所以要有个View类型的page字段表明当时操作的是哪个控件。position是用float类型表明的进展。除此之外,你还能发现一个特点“方向”,从0-1是左滑,从1-0是右滑。
所以在上面的操作之后,假如再进行左滑,你能够大胆的估测,tag为0的view的position会从-1到0,tag为1的view的position会从0到1。咱们能够看看是不是这样
能够看到结果正如咱们预料的那样。
3. 开始自界说动画
知道了transformPage的参数的含义之后,咱们就能十分便利的完成咱们自界说的切换动画作用。当然这个进程需要一定的想象力。
通过进展position,去逐渐改动view的一些特点(alpha、translation等等),这是不是瞬间就有点特点动画的意思了
刚开始不熟的话,咱们能够按照第二个Demo那样子给position去分区间判别,就不简单紊乱。
能够试着随便写一个旋转作用(一般这种横向切换也不会做旋转作用)
class NewPageTransformer : ViewPager2.PageTransformer {
override fun transformPage(page: View, position: Float) {
page.apply {
pivotY = (page.height / 2).toFloat()
pivotX = (page.width / 2).toFloat()
val w = width
when {
position < -1 -> {
}
position <= 0 -> {
rotation = -90 * position
translationX = -w * position
}
position <= 1 -> {
rotation = -90 * position
translationX = w * position
}
else -> {
}
}
}
}
}
能够看看作用
一般也不会做这种古怪的作用,这儿只是为了便利演示