属性动画在API 11
推出,目的是弥补帧动画和补间动画的不足,回顾其常用的使用方式。
ViewPropertyAnimator
可以直接使用View
对象进行链式调用,能够比较方便的创建动画。
编写一个简单的例子,布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
tools:context=".MainActivity">
<Button
android:id="@+id/bt_animation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="动画"
/>
RelativeLayout>
设置动画:
Button btn = findViewById(R.id.bt_animation);
float x = btn.getTranslationX();
btn.animate()//获取ViewPropertyAnimator对象
.translationX(x)//从当前位置移动
.translationX(400)//移动到400px
.setDuration(2000)//动画执行时间
.start();//开始执行动画,不调用此方法同样会执行
运行效果:
实际上btn.animate()
返回的就是ViewPropertyAnimator
对象。
ViewPropertyAnimator
对象还有一些其他的常用方法:
view.animate()//获取ViewPropertyAnimator对象
//位移
.translationX(100)
.translationXBy(100)
.translationY(100)
.translationYBy(100)
.translationZ(100)//Z轴移动,API 21 添加
.translationZBy(100)//API 21 添加
//改变坐标
.x(100)
.xBy(100)
.y(100)
.yBy(100)
//改变透明度
.alpha(0.1f)
.alphaBy(0.1f)
//改变透明度
.scaleX(0.1f)
.scaleXBy(0.1f)
.scaleY(0.1f)
.scaleYBy(0.1f)
//旋转
.rotation(180)
.rotationX(180)
.rotationBy(180)
.rotationY(180)
.rotationYBy(180)
//持续时间
.setDuration(1000)
.withStartAction(new Runnable() {
@Override
public void run() {
}
})//动画开始时执行runnable,API 16添加
.withEndAction(new Runnable() {
@Override
public void run() {
}
})//动画结束时执行runnable,API 16添加
.withLayer()//硬件加速,API 16添加
.setStartDelay(1000)//执行延迟
//设置插值器
.setInterpolator(new LinearInterpolator())
//设置更新监听
.setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
}
})
//动画监听
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
})
.start();
其中不带By
和带By
的方法区别:
.translationX(100)//直接移动到指定位置
.translationXBy(100)//在之前的位置基础上移动指定距离
//其他方法以此类推...
ObjectAnimator
其实是属性动画最常用的类,基本能满足日常动画编写。ObjectAnimator
封装了一系列的of
方法,根据实际情况来选用。
API 27
的of
系列方法:
首先看一个简单的例子:
Button btn = findViewById(R.id.bt_animation);
float x = btn.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "translationX", x, 400);
animator.setDuration(2000);
animator.start();
说明其参数意义:
- btn
为执行动画的对象,这里是Button
按钮;
- translationX
为需要操作的动画属性;
- x,400
为操作的起始值和结束值,中间还可插入一系列的数值,来满足动画的灵活变化;
同时ObjectAnimator
单独提供了setFloatValues(float... values)
方法,但是如果使用此方法
会将之前设置的第一组values
替换掉,需要注意一下。
ObjectAnimator
还可以设置插值器:
Button btn = findViewById(R.id.bt_animation);
float x = btn.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "translationX", x, 400);
animator.setInterpolator(new AccelerateInterpolator());//加速插值器
animator.setDuration(1000);
animator.start();
执行效果:
API 27
为止包含的系统插值器:
使用Property
封装的方法:
ObjectAnimator animator = ObjectAnimator.ofFloat(btn,
Property.of(Button.class, Float.class, "translationX"),
x, 400);
animator.setDuration(2000);
animator.start();
另外API 21
增加了Path
对象,这样可以执行更为复杂灵活的动画效果:
Button btn = findViewById(R.id.bt_animation);
Path path = new Path();
path.moveTo(btn.getX(),btn.getY());
path.lineTo(400,400);
//API 21 添加
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "translationX", "translationY", path);
animator.setDuration(2000);
animator.start();
}
说明下该方法的参数:
ObjectAnimator.ofFloat(Object target, String xPropertyName, String yPropertyName,
Path path)
target
动画执行的对象xPropertyName
X轴坐标yPropertyName
Y轴坐标Path
绘制动画路径类API 21
也可以使用Property
和Path
参数的方法:
ObjectAnimator animator = ObjectAnimator.ofFloat(btn,
Property.of(Button.class, Float.class, "translationX"),
Property.of(Button.class, Float.class, "translationY"),
path);
animator.setDuration(2000);
animator.start();
使用带TypeEvaluator
估值器参数的方法:
ObjectAnimator animator = ObjectAnimator.ofObject(btn, "translationX", new FloatEvaluator(), x, 400);
animator.setDuration(2000);
animator.start();
基本同ofFloat
方法一致。
在API 21
中ObjectAnimator
单独提供ofArgb
方法用于方便进行颜色动画的过渡计算:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ObjectAnimator
.ofArgb(btn, "backgroundColor",
Color.parseColor("#ff0000"),//红色
Color.parseColor("#0000ff"))//蓝色
.setDuration(2000)
.start();
}
另外ObjectAnimator
还有ofObject
的一些方法:
ObjectAnimator
.ofObject(btn,"translationX",new FloatEvaluator(),x,400)
.setDuration(2000)
.start();
上面这这段代码同样可以实现平移效果,看下该方法的参数:
public static ObjectAnimator ofObject(Object target, String propertyName,
TypeEvaluator evaluator, Object... values)
target
动画执行的对象PropertyName
属性名TypeEvaluator
估值器values
动画执行的可变参数
这里需要注意的是TypeEvaluator
中的evaluate()
方法返回类型必须和values
的参数类型一致,因为这里没有进行泛型约束,因此需要特别注意,该方法主要可以用于自定义的TypeEvaluator
和values
,因此在执行动画过程中,需要保证类型一致。
ObjectAnimator
还提供了非常重要的ofPropertyValuesHolder
系列方法,使用PropertyValuesHolder
参数可以使多个动画同时执行:
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX", x, 400);
PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("translationY", y, 400);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(btn, p1, p2);
animator.setDuration(2000);
animator.start();
PropertyValuesHolder
其实就是封装了要执行动画改变的属性和一系列的变化值,并且也拥有和ObjectAnimator
类似的各种ofInt
,ofFloat
,ofObject
等方法。
ofKeyframe
的方法可以设置动画的关键帧:
Keyframe k1 = Keyframe.ofFloat(0, x);
Keyframe k2 = Keyframe.ofFloat(0.5f, 100);
Keyframe k3 = Keyframe.ofFloat(1f, 400);
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX", k1, k2, k3);
ObjectAnimator.ofPropertyValuesHolder(btn,holder).setDuration(2000).start();
Keyframe.ofFloat(float fraction, float value)
方法中fraction代表动画执行的进度(0-1
之间),value代表这个进度需要执行的数值,也就是一帧的意思。
看下执行效果:
另外Keyframe
也可以设置插值器,和ObjectAnimator
比较类似,这里不再列出。
但是需要注意的是如果使用Keyframe
则必须至少有2帧添加到PropertyValuesHolder
中,否则会抛出异常:
java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
可以添加动画周期中的监听回调:
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
如果直接使用Animator.AnimatorListener
参数,需要实现的方法较多,可以选择AnimatorListenerAdapter
,它实现了Animator.AnimatorListener
接口,可以有选择的实现需要的接口。
该方法可以获取更新中的ValueAnimator
对象,从而获取其中包含的相关信息,编写业务逻辑。
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
}
});
setRepeatCount
:就是设置动画执行次数;
setRepeatMode
:设置重复模式 RESTART
,REVERSE
,INFINITE
;
setStartDelay
:设置动画执行延迟;
其他还有些方法,不一一分析了。