1. 补间动画
补间动画具体有四种如下图所示:
有两种实现方式:XML和java
//xml实现方式:
//1.定义一个xml
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:fromYDelta="0"
android:toYDelta="0"
android:toXDelta="200"
android:duration="500"
android:fillAfter="true">
</translate>
//2.在java中执行动画
//加载动画
Animation animation = AnimationUtils.loadAnimation(this, R.anim.demo);
//执行动画
testBtn.startAnimation(animation);
//java实现方式
TranslateAnimation translateAnimation = new TranslateAnimation(0,200,0,0);
translateAnimation.setDuration(500);//动画执行时间
translateAnimation.setFillAfter(true);//动画执行完成后保持状态
//执行动画
btn.startAnimation(translateAnimation);
2. 逐帧动画
逐帧动画有两种方式实现:XML和JAVA。如下所示:
// 方式1:xml
// 1. 设置XML资源文件
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true" // 设置是否只播放一次>
// 设置每一帧是100ms
<item android:drawable="@drawable/a0" android:duration="100"/>
<item android:drawable="@drawable/a1" android:duration="100"/>
<item android:drawable="@drawable/a2" android:duration="100"/>
<item android:drawable="@drawable/a3" android:duration="100"/>
<item android:drawable="@drawable/a4" android:duration="100"/>
<item android:drawable="@drawable/a5" android:duration="100"/>
<item android:drawable="@drawable/a6" android:duration="100"/>
<item android:drawable="@drawable/a7" android:duration="100"/>
<item android:drawable="@drawable/a8" android:duration="100"/>
<item android:drawable="@drawable/a9" android:duration="100"/>
<item android:drawable="@drawable/a10" android:duration="100"/>
</animation-list>
// 2. 在代码中设置资源文件
iv.setImageResource(R.drawable.demo);
animationDrawable = (AnimationDrawable) iv.getDrawable();
animationDrawable.start();
// 方式1:java方式
animationDrawable = new AnimationDrawable();
for (int i = 0; i <= 10; i++) {
int id = getResources().getIdentifier("a" + i, "drawable", getPackageName());
Drawable drawable = getResources().getDrawable(id);
animationDrawable.addFrame(drawable, 100);
}
iv.setImageDrawable(animationDrawable);
// 特别注意:在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次
animationDrawable.stop();
animationDrawable.start();
3. 属性动画
属性动画比补间动画有几个优势:
-
它不局限于View控件,可以是任意对象
-
它能够实现比补间动画更复杂的效果
-
它直接改变了对象的属性,而补间动画并没有
对属性动画有四个概念:
两个使用方法类:ValueAnimator
类 & ObjectAnimator
类
两个辅助使用类:插值器 & 估值器
3.1 ValueAnimator类
ValueAnimator
类的使用方法先是设置值,然后在onAnimationUpdate回调方法中对界面进行更新操作也就是手动的去更新界面。
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
// You can use the animated value in a property that uses the
// same type as the animation. In this case, you can use the
// float value in the translationX property.
float animatedValue = (float)updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});
ValueAnimator比较常用的有三种方法:
- ValueAnimator.ofInt(int values)
- ValueAnimator.ofFloat(float values)
- ValueAnimator.ofObject(int values)
3.2 ObjectAnimator类
ObjectAnimator类是ValueAnimator的子类,它内部自动实现了动画属性的更新。
ObjectAnimator animator = ObjectAnimator.ofFloat(mTextView, "rotation", 0,180,0);
animator.setDuration(2000);
animator.start();
以上代码的效果是控件旋转180度后又旋转回来。具体怎么更新界面由ObjectAnimator自动完成,这个也就是和ValueAnimator的区别。
3.3 插值器
插值器的作用是计算动画完成的进度,体现的是随着时间的推移进度的变化趋势。Android内置了9种内置的插值器实现:
用系统的AccelerateDecelerateInterpolator 来分析下是插值器是怎么个回事:
// 先加速再减速 差值器:AccelerateDecelerateInterpolator
@HasNativeInterpolator
public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
...
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
}
这是一个经过变化的余弦函数。x轴从0到1,y轴也是从0到1,如下图所示:
x轴代表的是时间进度,y轴代表的动画进度。正如上图表格中所描述的,AccelerateDecelerateInterpolator是先加速后降速,也就如图中所示曲线先平缓到陡峭最后又变得平缓。
3.4 估值器
估值器的作用是根据插值器的进度以及起始、终止点来计算最终的值,其中的进度就是插值器算出来的。
直接用系统自带的浮点估值器来举例子:
public class FloatEvaluator implements TypeEvaluator {
// FloatEvaluator实现了TypeEvaluator接口
...
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}
逻辑很简单。首先是实现TypeEvaluator接口,重写evaluate方法。具体的实现方法就是:起始值+(终点值-起始值)*进度,规规矩矩按着进度不断的变化结果。
参考资料
Android动画:献上一份详细 & 全面的动画知识学习攻略
Android 属性动画:这是一篇全面 & 详细的 属性动画 总结&攻略
Android 动画:插值器( Interpolator )和估值器(TypeEvaluator)