补间动画的作用对象是View,支持四种动画效果,分别是平移,缩放,旋转,透明度。补间动画既可以是单个动画,也可以有一系列动画组成。补间动画的四种分别对应Animation的四个子类(TranslateAnimation,ScaleAnimation,RotateAnimation,AlphaAnimation),除了以上四个子类它还有一个AnimationSet类,对应xml标签为
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="4000"
android:fromXDelta="0%p"
android:fromYDelta="0%p"
android:toXDelta="20%p"
android:toYDelta="20%p" />
<scale
android:duration="4000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.2"
android:toYScale="0.2" />
<rotate
android:duration="4000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<alpha
android:duration="4000"
android:fromAlpha="1.0"
android:toAlpha="0.2" />
set>
比如我们对TextView设置动画,使其点击后执行动画
txt.setOnClickListener {
it.startAnimation(AnimationUtils.loadAnimation(this, R.anim.animview))
}
Animation类的方法 | 作用 |
---|---|
reset() | 重置Animation的初始化 |
cancel() | 取消Animation动画 |
start() | 开始Animation动画 |
setAnimationListener() | 给当前Animation设置动画监听 |
hasStarted() | 判断当前Animation是否开始 |
hasEnded() | 判断当前Animation是否结束 |
clearAnimation() | 取消当View在执行的Animation动画 |
补间动画执行之后并未改变View的真实布局属性值。例如我们在Activity中有一个Button在屏幕上方,我们设置了平移动画移动到屏幕下方然后保持动画最后执行状态呆在屏幕下方,这时如果点击屏幕下方动画执行之后的Button是没有任何反应的,而点击原来屏幕上方没有Button的地方却响应的是点击Button的事件。在进行动画的时候,尽量使用dp,因为px会导致适配问题
插值器
插值器定义了动画的变化率,能帮助我们实现非线性改变的动画
xml | 描述 |
---|---|
@android:anim/accelerate_decelerate_interpolator | 动画始末速率较慢,中间加速 |
@android:anim/accelerate_interpolator | 动画开始速率较慢,之后慢慢加速 |
@android:anim/bounce_interpolator | 动画结束时弹起 |
@android:anim/decelerate_interpolator | 动画开始快然后慢 |
@android:anim/overshoot_interpolator | 向前弹出一定值之后回到原来位置 |
帧动画是顺序播放一组预先定义好的图片,不同于补间动画,系统提供了另外一个类AnimationDrawable来使用帧动画
在drawable文件夹下创建xml文件,如下所示:
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/text_bg" android:duration="180"/>
<item android:drawable="@drawable/text_bg2" android:duration="180"/>
<item android:drawable="@drawable/text_bg3" android:duration="180"/>
<item android:drawable="@drawable/text_bg4" android:duration="180"/>
animation-list>
执行动画,如下所示:
txt.setBackgroundResource(R.drawable.anim_zhen)
txt.setOnClickListener {
val animationDrawable = it.background as AnimationDrawable
animationDrawable.start()
}
出现的原因
在属性动画出现以前,Android主要有两种动画,帧动画(Frame Animation)和补间动画(Tween Animation),这两种动画统称为视图动画。帧动画是通过逐帧播放图片来实现动画效果,补间动画虽然提供了旋转、缩放、位移、透明度的动画效果,却有不可忽视的三大缺陷:
(1)作用对象有限,只能作用于View及其子类
(2)动画种类有限,只有旋转、缩放、位移、透明度4种动画
(3)只改变了View的显示效果,没有真正改变View的属性。例如:对View作位移的补间动画后,View虽然显示改变,但是响应区域却还在原来的位置
原理
属性动画通过在预设的规则下不断地改变值,并将值设置给作用对象的属性,从而达到动画效果。这个规则可以由我们定制,其中有两个重要的工具,可以帮助我们定制值的变化规则,一个是插值器(Interpolator),一个是估值器(TypeEvaluator)
插值器定义了动画的变化率,能帮助我们实现非线性改变的动画,如加速变化的AccelerateInterpolator
估值器的作用是计算出动画对应的最终的属性值。系统默认提供了3种估值器:
(1)IntEvaluator整型估值器,值的类型为整型
(2)FloatEvaluator浮点型估值器,值的类型为浮点型
(3)ArgbEvaluator,值的类型为ARGB值,可以用来计算颜色值
属性动画的使用
属性动画主要通过两个类来使用,ValueAnimator和ObjectAnimator,这两个的区别主要是:ValueAnimator只是计算值,赋值给对象属性需要我们手动监听值的变化来进行;ObjectAnimator则对赋值属性这一步封装进了内部,也就是自动赋值
ValueAnimator的使用
在res目录里创建animator目录,之后创建Animator resources file
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="30"
android:valueTo="200"
android:valueType="intType" />
ValueAnimator提供了回调以监听动画值,我们可以在此回调中拿到属性值并手动赋值给对象属性,从而达到效果,需要注意的是,对象是View的时候,有时需要我们在赋值属性后调用View.invalidate()或者View.requestLayout()方法来刷新界面实现视觉效果
val valueAnimator = AnimatorInflater.loadAnimator(this, R.animator.animator_hi) as ValueAnimator
//设置动画持续时间,以毫秒为单位
valueAnimator.duration = 2000
//设置插值器
valueAnimator.interpolator = DecelerateInterpolator()
//设置动画重复模式,RESTART表示动画正序重复,REVERSE代表倒序重复
valueAnimator.repeatMode = ValueAnimator.REVERSE
//设置重复次数,ValueAnimator.INFINITE表示无限重复
valueAnimator.repeatCount = 10
//设置动画延迟播放的时间
valueAnimator.startDelay = 1000
valueAnimator.addUpdateListener {
val value = it.animatedValue.toString()
txt.textSize = value.toFloat()
}
valueAnimator.start()
ObjectAnimator(ValueAnimator的子类)的使用
(1) ofInt(int… values):值的类型是int,会默认使用整形估值器
(2) ofFloat(float… values):值的类型是float,会默认使用浮点型估值器
(3) ofArgb(int… values):值的类型是代表颜色的32位的int,会默认使用ArgbEvaluator估值器
(4) ofObject(TypeEvaluator evaluator,Object… values):对应值的类型是Object,这种方式需要显式传入估值器,因为对于Object类型没有系统提供的估值器
/*
参数解释:
target:ObjectAnimator作用的对象
propertyName:属性名
values:过渡值(开始值、结束值)
*/
val objectAnimator = ObjectAnimator.ofFloat(txt, "textSize", 10f, 100f)
objectAnimator.duration = 3000
objectAnimator.repeatCount = Animation.INFINITE
objectAnimator.repeatMode = ValueAnimator.REVERSE
objectAnimator.start()
组合动画AnimatorSet
AnimatorSet用于把很多动画按照一定顺序组合起来播放,AnimatorSet采用了构造器模式来组合动画
val objectAnimator = ObjectAnimator.ofFloat(txt, "textSize", 10f, 100f)
val objectAnimator1 = ObjectAnimator.ofFloat(txt, "rotation", 0f, 360f)
objectAnimator.repeatCount = Animation.INFINITE
objectAnimator.repeatMode = ValueAnimator.REVERSE
objectAnimator1.repeatCount = Animation.INFINITE
objectAnimator1.repeatMode = ValueAnimator.REVERSE
val animatorSet = AnimatorSet()
animatorSet.duration = 3000
animatorSet.play(objectAnimator).with(objectAnimator1)
//将animator1和animator2一起播放
animatorSet.play(objectAnimator).with(objectAnimator1)
//将animator1插入animator2之后播放
animatorSet.play(objectAnimator).after(objectAnimator1)
//将animator1插入animator2之前播放
animatorSet.play(objectAnimator).before(objectAnimator1)
动画的监听
objectAnimator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?) {
}
})
objectAnimator.addPauseListener(object : AnimatorListenerAdapter() {
override fun onAnimationPause(animation: Animator?) {
}
})