这个例子的示例代码有ProxyDrawable.java,AnimateDrawable.java和AnimateDrawables.java。
Android 包android.graphics.drawable 中定义了一个Drawable 为所有Drawable的抽象基类。表示一个“可以绘制在屏幕的对象”。通常的情况下是从资源文件中读取各种不同类型的Drawable。和View不同的是Drawable不能接受处理事件不能和用户交互。Android自定义的Drawable有下列几种类型:
- Bitmap: 代表PNG或是JPEG图像。
- Nine Patch: PNG图像的一种扩展用法,多用来定义按钮边框,可以缩放。
- Shape: 简单的矢量几何图形。
- Layers: drawable 的集合组件,可以由多层Drawable叠加组合而成。
- States: drawable 的集合组件,可以从多个Drawable选择其一(一种状态)。
- Levels: drawable的集合组件, 可以根据Drawable的Level属性选择其一。
- Scale: drawable的集合组件, 使用一个Drawable但可以根据当前Level缩放Drawable。
此外也可以自定义Drawable,本例自定义了ProxyDrawable ,处理添加了一些检测基本上是和它代理的Drawable提供同样的功能。AnimateDrawable 是真正使用的自定义Drawable,它使用了Animation类来提供动画效果。
Android动画分为两种类型,一种称为“tweened”动画,主要是通过坐标变换:平移,旋转,缩放,色彩变化来显示动画效果,另外一种为“帧动画”由一幅一幅的图像连续显示而成。“tweened”动画由android.view.animation包中定义类来完成,而“帧动画”主要由AnimationDrawable 实现。
下面看看AnimateDrawable的void draw(Canvas canvas)实现
@Override
public void draw(Canvas canvas) {
Drawable dr = getProxy();
if (dr != null) {
int sc = canvas.save();
Animation anim = mAnimation;
if (anim != null) {
anim.getTransformation(
AnimationUtils.currentAnimationTimeMillis(),
mTransformation);
canvas.concat(mTransformation.getMatrix());
}
dr.draw(canvas);
canvas.restoreToCount(sc);
}
}
canvas.save()和canvas.restoreToCount(sc);是用来保存和回复Canvas的状态(Maxtrix等属性),因为我们需要修改Canvas的Matrix属性,canvas.concat方法都会和当前Canvas的Matrix进行矩阵运算,如果我么不保存之前的Matrix属性,每次都会很上次矩阵运算的结果相乘,对应本例来说,每次平移的距离会越来越大。
注:对于AnimateDrawable来说,Animation可以是任意类型:平移,缩放,旋转等。AnimateDrawables 中使用的是平移TranslateAnimation。
Animation an = new TranslateAnimation(0, 100, 0, 200);
an.setDuration(2000);
an.setRepeatCount(-1);
an.initialize(10, 10, 10, 10);
平移变换动画,定义了X,Y方向变化的范围X[0,100] ,Y[0,200],持续时间2秒。setRepeatCount为-1表示无限次。an.initialize(10, 10, 10, 10)对于TranslateAnimation来说无多大实际意义,只要void initialize(int width, int height, int parentWidth, int parentHeight) 中width,height不为0即可。
AnimateDrawables 的onDraw 方法:
@Override protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
mDrawable.draw(canvas);
invalidate();
}
onDraw里面又调用了invalidate方法,又会触发onDraw,这样动画就会一直运行下去。