Android帧动画的实现原理,Android Animation(帧动画)原理个人见解

Android 动画分三大类

Frame Animation (帧动画)

Tween Animation (补间动画)

Property Animator (属性动画) 3.0之后

同时,复杂程度,也是从简到繁,由易到难,今天先说帧动画。

帧动画的使用方式网络上很多很多,也很简单,就不多扯淡,主要说下原理。

原理引入

ImageView iv_anima = (ImageView) findViewById(R.id.iv);

AnimationDrawable ad =(AnimationDrawable) iv_anima.getBackground();

ad.start();

在使用帧动画的时候,会给 ImageView 设置 backgroud,并将backgroud 的drawable 对象 转化为AnimationDrawable 对象,然后用此对象去启动动画。那么问题来了,我们去看看这个牛逼的类

AnimationDrawable :

AnimationDrawable 是创建帧动画的,定义一系列的drawable对象,并且以XML文件的形式放到res/drawable/folder文件夹下,同时将此drawable对象设置到view的backgroud属性.

AnimationDrawable重要属性

oneshot 动画播放次数,ture表示只播放一次,false表示循环播放

duration 动画播放时间(每帧)

AnimationDrawable如何将对象转换为动画的

由上面的源码得知,createFromXml()方法的使用,将xml文件转化了,转换为什么?接着看源码

public static Drawable createFromXml(Resources r, XmlPullParser parser, Theme theme)

throws XmlPullParserException, IOException {

AttributeSet attrs = Xml.asAttributeSet(parser);

int type;

while ((type=parser.next()) != XmlPullParser.START_TAG &&

type != XmlPullParser.END_DOCUMENT) {

// Empty loop

}

if (type != XmlPullParser.START_TAG) {

throw new XmlPullParserException("No start tag found");

}

Drawable drawable = createFromXmlInner(r, parser, attrs, theme);

if (drawable == null) {

throw new RuntimeException("Unknown initial tag: " + parser.getName());

}

return drawable;

}

public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,

Theme theme) throws XmlPullParserException, IOException {

final Drawable drawable;

final String name = parser.getName();

switch (name) {

case "selector":

drawable = new StateListDrawable();

break;

case "animated-selector":

drawable = new AnimatedStateListDrawable();

break;

case "level-list":

drawable = new LevelListDrawable();

break;

case "layer-list":

drawable = new LayerDrawable();

break;

case "transition":

drawable = new TransitionDrawable();

break;

case "ripple":

drawable = new RippleDrawable();

break;

case "color":

drawable = new ColorDrawable();

break;

case "shape":

drawable = new GradientDrawable();

break;

case "vector":

drawable = new VectorDrawable();

break;

case "animated-vector":

drawable = new AnimatedVectorDrawable();

break;

case "scale":

drawable = new ScaleDrawable();

break;

case "clip":

drawable = new ClipDrawable();

break;

case "rotate":

drawable = new RotateDrawable();

break;

case "animated-rotate":

drawable = new AnimatedRotateDrawable();

break;

case "animation-list":

drawable = new AnimationDrawable();

break;

case "inset":

drawable = new InsetDrawable();

break;

case "bitmap":

drawable = new BitmapDrawable();

break;

case "nine-patch":

drawable = new NinePatchDrawable();

break;

default:

throw new XmlPullParserException(parser.getPositionDescription() +

": invalid drawable tag " + name);

}

drawable.inflate(r, parser, attrs, theme);

return drawable;

}

很明显,直接将xml文件经过XmlPullParser解析转换成了drawable对象,createFromXmlInner()方法中,根据不同的标签名称去生成不同的drawable,最后去调用inflate方法。

到此,我们已经基本理清了从XML文件到Drawable对象的转换流程。对帧动画的工作原理有了一个小了解,这样,也许会让我们对帧动画的使用更加的熟练。那么问题来了,帧动画animation-list节点下的节点是如何形成一个个帧动画效果的?我们继续往下看:

private final static class AnimationState extends DrawableContainerState

private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,

Theme theme) throws XmlPullParserException, IOException {

int type;

final int innerDepth = parser.getDepth()+1;

int depth;

while ((type=parser.next()) != XmlPullParser.END_DOCUMENT

&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {

if (type != XmlPullParser.START_TAG) {

continue;

}

if (depth > innerDepth || !parser.getName().equals("item")) {

continue;

}

final TypedArray a = obtainAttributes(r, theme, attrs,

R.styleable.AnimationDrawableItem);

final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1);

if (duration < 0) {

throw new XmlPullParserException(parser.getPositionDescription()

+ ": tag requires a 'duration' attribute");

}

Drawable dr = a.getDrawable(R.styleable.AnimationDrawableItem_drawable);

a.recycle();

if (dr == null) {

while ((type=parser.next()) == XmlPullParser.TEXT) {

// Empty

}

if (type != XmlPullParser.START_TAG) {

throw new XmlPullParserException(parser.getPositionDescription()

+ ": tag requires a 'drawable' attribute or child tag"

+ " defining a drawable");

}

dr = Drawable.createFromXmlInner(r, parser, attrs, theme);

}

mAnimationState.addFrame(dr, duration);

if (dr != null) {

dr.setCallback(this);

}

}

}

上面的代码中我们可以看出, AnimationState 是继承 DrawableContainerState 的,在DrawableContainerState这个类中有一个成员变量Drawable[] mDrawables;用于保存drawable信息。

在 inflateChildElements 这方法里面通过TypeArray获取drawable的信息,然后调用AnimationState的addFrame方法,将一系列动画信息就存储在drawable数组中。

public void start() {

mAnimating = true;

if (!isRunning()) {

// Start from 0th frame.

setFrame(0, false, mAnimationState.getChildCount() > 1

|| !mAnimationState.mOneShot);

}

}

通过setFrame方法设置我们的drawable。接着就可以进行drawable的展示了。

帧动画的大概原理就是这样,个人见解,希望能帮到其他人。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值