1. 简介
属性动画(Property animation)
Android4.4之后增加了属性动画
在 XML 中定义的动画,用于在设定的一段时间内修改目标对象的属性,例如背景颜色或 alpha 值。位于android.animation
包下的类
文件位置: res/animator/filename.xml
,编译后的数据类型为ValueAnimator
、ObjectAnimator
、AnimatorSet
- xml方式:
<set
android:ordering=["together" | "sequentially"]>
<objectAnimator
android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["restart" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["restart" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<set>
...
</set>
</set>
使用:
val button = findViewById<Button>(R.id.button)
val set: AnimatorSet = AnimatorInflater.loadAnimator(myContext, R.animator.property_animator)
.apply {
setTarget(button)
start()
}
- Java代码方式
val ivImage = findViewById<ImageView>(R.id.ivImage)
val objectAnimator = ObjectAnimator.ofFloat(ivImage,"scaleX",1f,2f)
objectAnimator.repeatCount = ValueAnimator.INFINITE
objectAnimator.duration = 10
objectAnimator.startDelay = 5
objectAnimator.repeatMode = ValueAnimator.RESTART
objectAnimator.interpolator = LinearInterpolator()
objectAnimator.start()
ValueAnimator
和ObjectAnimator
的区别:
- ValueAnimator先改变值,再手动赋值给对象属性
- ObjectAnimator先改变值,再自动赋值给对象属性
继承关系
Animator
-> AnimatorSet
-> ValueAnimator
-> ObjectAnimator
-> TimeAnimator
2. ValueAnimator
// 设置操作属性的一系列值
public static ValueAnimator ofFloat(float... values) {
ValueAnimator anim = new ValueAnimator();
anim.setFloatValues(values);
return anim;
}
public static ValueAnimator ofInt(int... values) {
ValueAnimator anim = new ValueAnimator();
anim.setIntValues(values);
return anim;
}
ofObject(TypeEvaluator evaluator, Object... values)
// 用于组合动画
ofPropertyValuesHolder(PropertyValuesHolder... values)
//...
ofxxx()
接收可变参数,传进去的一系列值表示动画时的变化范围
val valueAnim = ValueAnimator.ofFloat(0,100)
valueAnim.duration=200
valueAnim.addUpdateListener {
val animatedValue = it.animatedValue as Float
// x轴不断偏移
ivImage.translationX = animatedValue
}
ValueAnimator
是计算动画过程中变化的值,开始、结束、持续时间等属性,最终将计算出来的值应用到对象上,是必须通过回调实现的,所以ValueAnimator必须注册监听才能更新到需要执行动画的对象上
3. ObjectAnimator
开发中常用的是ObjectAnimator
,它没有ValueAnimator麻烦,是自动赋值给对象
// 第一个参数:传入的object对象,第二个参数:属性名,后面参数为可变参数
val objectAnimator = ObjectAnimator.ofFloat(ivImage, "rotation", 0, 360)
objectAnimator.duration = 10
objectAnimator.start()
上面第2个参数PropertyValuesHolder
中可以找到相关设置
String methodName = getMethodName("set", mPropertyName);
mGetter = setupSetterOrGetter(targetClass, sGetterPropertyMap, "get", null);
像位移属性translationX
、translationY
,缩放属性scaleX
、scaleY
,旋转属性rotation
等等都可以操作,任何属性只要有get
和set
方法,我们都可以操作
4. 监听
- ValueAnimator中的
interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
public void addUpdateListener(AnimatorUpdateListener listener)
- Animator中
interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
public void addListener(AnimatorListener listener)
- AnimatorListenerAdapter
objectAnimator.addListener(object :AnimatorListenerAdapter(){
// 按需复写
})
- kotlin的可选参数支持
objectAnimator.addListener (onEnd = {}){
it.start()
}
5. 组合动画
先看看AnimatorSet
的几个方法
public Builder play(Animator anim)// 创建一个Builder对象
public void playTogether(Animator... items)// 同时执行
public void playSequentially(Animator... items)// 按顺序执行
再看看AnimatorSet.Builder
下的几个方法
public Builder with(Animator anim) // 将现有动画和传入的动画同时执行
public Builder before(Animator anim) // 将现有动画插入到传入动画之前执行
public Builder after(Animator anim)// 将现有动画插入到传入动画之后执行
看看怎么用的
val objectAnimator = ObjectAnimator.ofFloat(ivImage, "scaleX", 1f, 2f)
val objectAnimator2 = ObjectAnimator.ofFloat(ivImage, "scaleY", 1f, 2f)
val animatorSet = AnimatorSet()
// animatorSet.playTogether(objectAnimator,objectAnimator2)
animatorSet.play(objectAnimator).with(objectAnimator2)
animatorSet.start()