Android Animation parsing (1) -- Frame Animation (Frame Animation)

Source: Internet
Author: User

Android Animation parsing (1) -- Frame Animation (Frame Animation)

Animation plays an important role in our actual development. An excellent animation can add a lot of colors to our app. At the same time, an excellent animation link can increase the logic display of our app. In the Android system, the system provides support for several types of animations: Frame Animation and Tween Animation) and the Property Animator (Property animation) added after the 3.0 system ). The Skillful Use of these animations can help us design an animation for the perfect effect. Let's start learning it now!

I. Overview
Frame Animation, as its name implies, is the combination of frames. The animation display effect can be achieved by setting the image display sequence.

In Android development, the system provides the "animation-list" Node for configuring frame animation.

Steps

1. Create an anim folder in the res directory to store xml animation files. res/anim can also be stored in the drawable directory.

2. Configure the animation item in the animation-list node.

2. Set the file to the background of the ImageView control, and then obtain the background and convert it to an AnimationDrawable object for playing the animation.

    iv_imageView.setBackgroundResource(R.drawable.frame_animation);    AnimationDrawable animation = (AnimationDrawable)iv_imageView.getBackground();    animation.start();

Ii. Examples

1. Running Pegasus
Let's take a look at the first instance, the flying Pegasus.

Frame Animation can be used for this animation effect. We only need to cut the GIF Animation into an image by Frame, and then we can specify the order of the image in the animation-list tag for playing.

Code Implementation

<code class=" hljs xml"><animation-list xmlns:android="http://schemas.android.com/apk/res/android">        <item android:drawable="@mipmap/Horse_start" android:duration="200">        <item android:drawable="@mipmap/Horse1" android:duration="200">        <item android:drawable="@mipmap/Horse2" android:duration="200">        <item android:drawable="@mipmap/Horse3" android:duration="200">        <item android:drawable="@mipmap/Horse4" android:duration="200">        <item android:drawable="@mipmap/Horse5" android:duration="200">        <item android:drawable="@mipmap/Horse6" android:duration="200">        <item android:drawable="@mipmap/Horse7" android:duration="200">        <item android:drawable="@mipmap/Horse8" android:duration="200">        <item android:drawable="@mipmap/Horse_start" android:duration="200">    </item></item></item></item></item></item></item></item></item></item></animation-list></code>

In the animation-list, the order of items is the order in which images are played in the animation. After the sequence is set, we will bind the anim to our ImageView and play it.

    
  

The last step is our code. Get the drawable and play it.

    ImageView iv_animaView = (ImageView) findViewById(R.id.iv_frame);    AnimationDrawable animationDrawable = (AnimationDrawable) iv_animaView.getBackground();    animationDrawable.start();

View the animation effect:

Isn't it easy? A few simple lines of code can make a gif animation effect, but now it seems that there are open-source controls that can load gif images. Let's look back at the efficiency of the two.

2. streaking robots
Through the previous case, we are already familiar with the use of Frame Animation. Next we will provide an example to consolidate the knowledge points.

Code Implementation

<code class=" hljs xml"><animation-list xmlns:android="http://schemas.android.com/apk/res/android">        <item android:drawable="@mipmap/zzlx1" android:duration="200">        <item android:drawable="@mipmap/zzlx2" android:duration="200">        <item android:drawable="@mipmap/zzlx3" android:duration="200">        <item android:drawable="@mipmap/zzlx4" android:duration="200">        <item android:drawable="@mipmap/zzlx5" android:duration="200">        <item android:drawable="@mipmap/zzlx6" android:duration="200">        <item android:drawable="@mipmap/zzlx7" android:duration="200">        <item android:drawable="@mipmap/zzlx8" android:duration="200">    </item></item></item></item></item></item></item></item></animation-list></code>

The code below is the same as above. We only need to look at our implementation results.

Iii. Analysis of Frame Animation principles
In the above development, we are converting the Drawable object corresponding to backgroud into an AnimationDrawable object, and then starting Frame Animation by this object. Where is this class holy? Let's look at it together.

1. AnimationDrawable Overview
AnimationDrawable is used to create a frame-by-frame animation. It defines the Drawable object of some columns that can be used to set the backgroud background attribute of the View. The simplest way to create a frame-by-frame animation is to create an XML file and put the xml file in the res/drawable/folder, set this drawa object to the backgroud attribute of the view. Xml file composition:

Animation-list: root node, including a series of item items: each item corresponds to a frame)

The following code creates and uses Frame Animation:

    ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);    img.setBackgroundResource(R.drawable.spin_animation);    AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();    frameAnimation.start();

Let's take a look at the Attributes provided by the AnimationDrawable object.

AnimationDrawable_visible: sets whether to be visible; Animation: AnimationDrawable_oneshot: sets whether to play only once, true is, false no AnimationDrawableItem_duration: sets the interval between animation frames; Setting the drawable object between frames

2. AnimationDrawable source code analysis
We have made a brief analysis on the AnimationDrawable and learned about its attributes. We still have some questions about Frame Animation, such:

How does AnimationDrawable form frames? How does Frame Animation achieve continuous loop playback? Can we use code to Control Frame Animation playback?

Next we will analyze AnimationdDrawable based on the above issues. View the source code. We can see the public method exposed by AnimationDrawable.

Based on the name of the AnimationDrawable, we can also calculate that this is a Drawable sub-class. Let's take a closer look at why the Drawable object obtained through the getBackgroud () method can be converted to the AnimationDrawable sub-class? This requires us to look at the source code. In the Drawable class, there is a createFromXml () method: <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4NCjxwcmUgY2xhc3M9 "brush: java;"> /** * Create a drawable from an XML document. For more information on how to * create resources in XML, see * Drawable Resources. */ public static Drawable createFromXml(Resources r, XmlPullParser parser) throws XmlPullParserException, IOException { return createFromXml(r, parser, null); }

This method is used to convert my XML file into a drawable object. Let's go further and look at the createFromXml () method.

    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;    }

Here we can see that the XML file is converted into Drawable. In the Android system, Xml files are parsed through XmlPullParser. In the above method, first, the start and end labels of the xml file are used to determine whether the xml file contains empty nodes. Then pass:

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

Parse the XML file and convert it to a Drawable object.

    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;    }

In the createFromXmlInner method, first obtain the labels of all our xml files, and then root the corresponding label name to create the corresponding drawable object, such as the AnimationDrawable object we created this time. Then, call the inflater () method. Because the inflater method has been rewritten in the AnimationDrawable method, this is:

    @Override    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)            throws XmlPullParserException, IOException {        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable);        super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible);        updateStateFromTypedArray(a);        a.recycle();        inflateChildElements(r, parser, attrs, theme);        setFrame(0, true, false);    }

So far, we have basically clarified the conversion process from an XML file to a Drawable object. Now we will begin to analyze how nodes under the animation-list node form a frame animation effect. Before analyzing, we should first understand the AnimationState class. This class is used to store our series of drawable. Source code:

    private final static class AnimationState extends DrawableContainerState

This class inherits the DrawableContainerState class. DrawableContainerState has a member variable Drawable [] mDrawables; used to store our drawable information. To understand this, we can analyze the inflateChildElements method.

    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);            }        }    }
   
  

In this method, you can use TypeArray to obtain information about drawable, call the addFrame method of mAnimationState, and store a series of animation information in the drawable array.

Through the above analysis, a series of animations have been transferred out and stored. Our next task is to analyze the start and enable the analysis animation.

    public void start() {        mAnimating = true;        if (!isRunning()) {            // Start from 0th frame.            setFrame(0, false, mAnimationState.getChildCount() > 1                    || !mAnimationState.mOneShot);        }    }

Use the setFrame method to set our drawable, which contains selectDrawable (frame.

The basic process is like this. You can simply understand and use it. Next I will analyze several animation articles.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.