安卓中,动画可以分为三类。逐帧动画,补间动画,属性动画。稍微小结下,我对这三个动画的认识。
逐帧动画
AnimationDrawble,所以逐帧动画,其实是一种图像。通过设置ImageView类的background好或者src从代码和xml两个方式上载入。
纯代码
AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
frameAnimation.start();
xml定义
<animation-list android:id="@+id/selected" android:oneshot="false">
<item android:drawable="@drawable/ wheel0" android:duration="50" />
<item android:drawable="@drawable/wheel1" android:duration="50" />
<item android:drawable="@drawable/wheel2" android:duration="50" />
</animation-list>
补间动画
补间:开发者只需要给出动画的起始和结束帧状态,中间的帧交由安卓系统计算和补齐。抽象类Animation是补间动画的基类。同样可以分为xml和纯代码两种方式显示。补间动画无法实现动画无限重复播放。
涉及的API
AlphaAnimation,ScaleAnimation,RotateAnimation,TranslateAnimation,AnimationSet,Interpolator(差值接口),TimeInterpolator,Transformation,Camera(三维图形变换,类似Matrix)
Animation animation = AnimationUtils.loadAnimation(Context context,int id)
实现自定义补间动画
继承Animation,重写initalize()方法和applyTransformation(float interpolatedTime,Transformation t)方法
- interpolatedTime:代表了动画的时间进行比,不管动画实际的持续时间如何,当动画播放时,该参数总是自动从0变化到1.
- Transformation 该参数代表了补间动画在不同时刻对图形或组件的变形程度。
applyTransformation方法的参考代码:
camera.save();
camera.rotateY(360 *interpolatedTime);
Matrix matrix = transformation.getMatrix();
camera.getMatrix(matrix);
matrix.preTranslate(-centerX,-centerY);
camera.restore();
属性动画
属性动画主要有两方面组成:1计算各帧的相关属性值 2为指定对象设置这些计算后的值。
对象的属性名称有:rotationX,rotationY,scaleX,scaleY,alpha,translationX,translationY
监听事件 ValueAnimator.AnimatorUpdateListener , Animator.AnimatorListener
涉及的API
Animator:属性动画的基类。
- ValueAnimator: 负责第一方面的内容。因此第二方面,为指定对象设置属性值须由程序员通过监听来完成。
- ObjectAnimator,是ValueAnimator的子类,使用起来更简单。
- AnimatorSet(属性动画组合),它是Animator的子类,用于组合多个Animator,指定播放顺序。
Evaluator 计算器,控制属性动画如何计算属性值.TypeEvaluator 计算器接口,通过实现该接口来实现自定义计算器。
- IntEvaluator
- FloatEvaluator
- ArgbEvaluator
- PointFEvaluator
- RectEvaluator
ValueAnimator的使用
基本用法
- 调用ValueAnimator的ofInt(),ofFloat()或ofObject静态方法创建
- 设置持续时间,插值方式,动画模式等属性
- 注册监听器AnimationUpdateListerner,在监听方法里,通过getAnimatedValue()方法,把当前帧的值应用到所需要的对象上。
- start()启动动画
如果getAnimatedValue()返回的不是系统默认的值,借助TypeEvaluator接口,用系统自带的实现类,如PointFEvaluator,FloatArrayEvaluator,或者自己实现TypeEvaluetor,重写evaluator方法。
代码如下:
valueAnimator.setObjectValues(new PointF(0, 0));
valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
Log.e("evaluate","fraction="+fraction + " startValue="+startValue +" endValue=" + endValue);
PointF pointF = new PointF();
pointF.x = 200 * fraction * 3;
pointF.y = (float) (0.5 * 10 * 200 * fraction * fraction);
return pointF;
}
});
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF = (PointF) animation.getAnimatedValue();
ball.setTranslationX(pointF.x);
ball.setTranslationY(pointF.y);
}
});
ObjectAnimator的使用
继承自ValueAnimator,完成了属性动画的两个方面,所以可以直接把动画应用到对象上。
注意事项
- 该对象存在对应属性的setter方法。
- 如果只提供一个值,则该值被认为是结束值,此时需要提供getter方法。
- 如果该对象的setter方法不会自动调用invalidate()方法,则需要在onAnimationUpdate()监听方法里调用invalidate()刷新屏幕。
xml定义属性动画
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="600"
android:interpolator="@android:interpolator/accelerate_decelerate"
android:propertyName="alpha"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
/>
Animator animator = AnimatorInflator.loadAnimator(Context context,int resId);
多个属性动画同时播放的实现
1、通过AnimatorSet
AnimatorSet s = new Animatorset();
s.play(animator1).before(animator2);
s.paly(animator2).befor(animator3);
2、 ValueAnimator,ObjectAnimater的AnimatorUpdateListener监听方法onAnimationUpdate里,调用对象的多个属性setter即可。
3、借助PropertyValuesHolder
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("alpha",1f,0f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleX",1f,0f);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f);
ObjectAnimator animator1 = ObjectAnimator.ofPropertyValuesHolder(txt,holder1, holder2, holder3);
animator1.setDuration(800);
animator1.setInterpolator(new AccelerateDecelerateInterpolator());
animator1.setRepeatMode(ValueAnimator.REVERSE);
animator1.setRepeatCount(ValueAnimator.INFINITE);
animator1.setStartDelay(1000);
animator1.start();
借助ViewPropertyAnimator实现同时播放动画
//need API12
mBlueBall.animate()//
.alpha(0)//
.y(mScreenHeight / 2).setDuration(1000)
// need API 12
.withStartAction(new Runnable()
{
@Override
public void run()
{
Log.e(TAG, "START");
}
// need API 16
}).withEndAction(new Runnable()
{
@Override
public void run()
{
Log.e(TAG, "END");
runOnUiThread(new Runnable()
{
@Override
public void run()
{
mBlueBall.setY(0);
mBlueBall.setAlpha(1.0f);
}
});
}
}).start();
等效于:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 0,
mScreenHeight / 2, 0);
ObjectAnimator.ofPropertyValuesHolder(mBlueBall, pvhX, pvhY).setDuration(1000).start();
p.s. 参考《疯狂安卓讲义》
Android 属性动画(Property Animation) 完全解析 (下)