Android Animation(帧动画)原理个人见解
2016-09-02 15:18
381 查看
Android 动画分三大类
Frame Animation (帧动画)
Tween Animation (补间动画)
Property Animator (属性动画) 3.0之后
同时,复杂程度,也是从简到繁,由易到难,今天先说帧动画。
帧动画的使用方式网络上很多很多,也很简单,就不多扯淡,主要说下原理。
在使用帧动画的时候,会给 ImageView 设置 backgroud,并将backgroud 的drawable 对象 转化为AnimationDrawable 对象,然后用此对象去启动动画。那么问题来了,我们去看看这个牛逼的类
AnimationDrawable :
AnimationDrawable 是创建帧动画的,定义一系列的drawable对象,并且以XML文件的形式放到res/drawable/folder文件夹下,同时将此drawable对象设置到view的backgroud属性.
AnimationDrawable重要属性
oneshot 动画播放次数,ture表示只播放一次,false表示循环播放
duration 动画播放时间(每帧)
AnimationDrawable如何将对象转换为动画的
由上面的源码得知,createFromXml()方法的使用,将xml文件转化了,转换为什么?接着看源码
很明显,直接将xml文件经过XmlPullParser解析转换成了drawable对象,createFromXmlInner()方法中,根据不同的标签名称去生成不同的drawable,最后去调用inflate方法。
到此,我们已经基本理清了从XML文件到Drawable对象的转换流程。对帧动画的工作原理有了一个小了解,这样,也许会让我们对帧动画的使用更加的熟练。那么问题来了,帧动画animation-list节点下的节点是如何形成一个个帧动画效果的?我们继续往下看:
上面的代码中我们可以看出, AnimationState 是继承 DrawableContainerState 的,在DrawableContainerState这个类中有一个成员变量Drawable[] mDrawables;用于保存drawable信息。
在 inflateChildElements 这方法里面通过TypeArray获取drawable的信息,然后调用AnimationState的addFrame方法,将一系列动画信息就存储在drawable数组中。
通过setFrame方法设置我们的drawable。接着就可以进行drawable的展示了。
帧动画的大概原理就是这样,个人见解,希望能帮到其他人。
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如何将对象转换为动画的
/** * Create a drawable from an XML document. For more information on how to * create resources in XML, see * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>. */ public static Drawable createFromXml(Resources r, XmlPullParser parser) throws XmlPullParserException, IOException { return createFromXml(r, parser, null); }
由上面的源码得知,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() + ": <item> 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() + ": <item> 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的展示了。
帧动画的大概原理就是这样,个人见解,希望能帮到其他人。
相关文章推荐
- android 动画原理源码分析之Animation
- Android Animation动画原理源码分析
- Android动画Animation运行原理解析
- Android Animation动画开始的两个方法(个人)
- android动画使用分析[animation原理]
- Android的animation的四种动画
- Android animation 定义动画
- Android 动画效果 --Animation 动画(讲解了所有的Android动画效果,是一个值得收藏的帖子)
- Android应用通过AnimationDrawable实现View的动画效果
- Android开发之Animation 4种动画效果
- Android Animation动画
- android三种动画实现原理及使用
- Android动画开发——Animation显示隐藏菜单效果
- Android的Animation之LayoutAnimation使用方法(控件设置动画)
- 利用Android属性动画实现Banner的原理与实践
- Android_Animation动画
- Android动画的实现Animation
- Android SpringAnimation 弹簧动画
- Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition
- android动画知识个人记录