In-depth analysis of Android property Animation: making you an animation cool

Source: Internet
Author: User


Preface

Thank you for reading this article. I firmly believe that reading this article will not disappoint you. Want to be an animated cool? Want to be proficient in animation? Therefore, you must master all the content in this article. I have already written two blog posts about animation, but I still haven't fully described the animation. So I wrote this article. In addition, I will write another source code analysis on the property animation, through these four blog posts, you will truly become an animated cool.

Android animation series:

Android animation Overview

Android animation advanced-use the open source animation library nineoldandroids

In-depth analysis of Android property Animation: making you an animation cool

Android source code analysis-why do I write this blog post about how property animation works?

It is the spirit of sharing. I have experienced a process from getting familiar with animations. It may take several days or hours to get familiar with animations, in short, you don't have to spend at least a few hours to get familiar with all the animations. I spent a lot of time figuring out the entire animation logic and knowing how hard it was, so I don't want everyone to be like me anymore. I want everyone to get familiar with and be proficient in animation more quickly. Through this article, you will have a deep understanding of Android animation and will never be able to see it again. Specifically, this article analyzes attribute animation in depth, because View animation and Frame Animation have limited functions and are relatively simple, and there are not many things worth analyzing.

Opening

Like the design pattern, we also raised a question to introduce our content.

Problem:

Add an animation to the Button to increase the width of the Button from the current width to 500px.

You may say that this is very simple. You can do it with a gradient animation. Let's try it. Can you write it out? Soon you will suddenly realize that the original gradient animation does not support width animation at all. Yes, the gradient animation only supports four types: Translation and rotation), Scale, and opacity ). Of course, you can use scaleX to enlarge the Button in the x direction. It seems that the width is increased. Actually, it is not, but the Button is enlarged, in addition, because the Button is zoomed in only the x direction, the background of the Button and the text above are stretched, and the Button may even exceed the screen. Below is

The above effect is obviously very poor, and it is not really a width animation. However, fortunately, we still have property animation. Let's try it with property animation.

View demo

    private void performAnimate() {        ObjectAnimator.ofInt(mButton, width, 500).setDuration(5000).start();    }    @Override    public void onClick(View v) {        if (v == mButton) {            performAnimate();        }    }

The above code runs and finds that it is ineffective. In fact, it is right. If you pass an attribute at will, there will be no animation effect if it is light, and the program will Crash directly if it is heavy.

The following describes the principles of property Animation:

Property animation requires that the animation objects provide get and set methods for this property. Property animation depends on the initial value and final value you pass, the set method is called multiple times based on the animation effect. The values passed to the set method are different each time. Specifically, the passed value is closer and closer to the final value over time. To sum up, if you want to make the animation take effect for the object property xxx, you must satisfy two conditions at the same time:

1. the setXxx method must be provided for the object. If the initial value is not transmitted during the animation, The getXxx method must be provided because the system wants to get the initial value of the xxx attribute (if this parameter is not met, the program directly Crash)

2. The changes made by setXxx of the object to the property xxx must be reflected in some way, such as the changes to the ui (if this item is not met, the animation will be ineffective but will not Crash)

The preceding conditions are indispensable.

So why is it ineffective to animation the width attribute of the Button? This is because although the getWidth and setWidth methods are provided inside the Button, the setWidth method does not change the size of the View. It is a newly added method of TextView, And the View does not have this setWidth method, because the Button inherits TextView, the Button has the setWidth method. Let's take a look at the source code of the getWidth and setWidth methods:

    /**     * Makes the TextView exactly this many pixels wide.     * You could do the same thing by specifying this number in the     * LayoutParams.     *     * @see #setMaxWidth(int)     * @see #setMinWidth(int)     * @see #getMinWidth()     * @see #getMaxWidth()     *     * @attr ref android.R.styleable#TextView_width     */    @android.view.RemotableViewMethod    public void setWidth(int pixels) {        mMaxWidth = mMinWidth = pixels;        mMaxWidthMode = mMinWidthMode = PIXELS;        requestLayout();        invalidate();    }    /**     * Return the width of the your view.     *     * @return The width of your view, in pixels.     */    @ViewDebug.ExportedProperty(category = layout)    public final int getWidth() {        return mRight - mLeft;    }

From the source code, we can see that getWidth does get the width of the View, while setWidth is the exclusive method of TextView and its subclass. It does not set the width of the View, instead, it sets the maximum and minimum width of TextView. This is not the same as the TextView width. Specifically, the TextView width corresponds to the android: layout_width attribute in Xml, textView also has an attribute android: width, which corresponds to the setWidth method of TextView. Okay, I admit that my description is a bit confusing, but this is indeed the case, and I have not found any important use of this android: width attribute yet, it seems useless. I will not go into it here, or else I will go away from the topic. In short, the setWidth and getWidth of TextView and Button are not the same thing, and the width of the control cannot be changed through setWidth. Therefore, attribute animation on width is ineffective, in this example, the animation does not take effect because it only meets condition 1 and does not meet condition 2.

To address the above problems, Google tells us 3 solutions:

1. Add the get and set methods to your object. If you have the permission

2. Use a class to wrap the original object and indirectly provide the get and set methods for it.

3. Use ValueAnimator to listen to the animation process and change attributes.

It looks a little abstract, but don't worry. I will introduce it one by one below.

Animation of any attribute

Here we will give a detailed introduction to the three solutions proposed above:

Add the get and set methods to your object. If you have the permission

This is very understandable. If you have the permission, you can add get and set. However, we often do not have the permission to do so, for example, the problems mentioned at the beginning of this article, you cannot add a required setWidth Method to the Button because it is implemented in the Android SDK. This method is the simplest, but it is often not feasible. More analysis is not performed here.

Uses a class to wrap the original object and indirectly provides the get and set methods for it.

This is a very useful solution, and I like it most, because it is very convenient to use and easy to understand. Here we will introduce it through a specific example.

    private void performAnimate() {        ViewWrapper wrapper = new ViewWrapper(mButton);        ObjectAnimator.ofInt(wrapper, width, 500).setDuration(5000).start();    }    @Override    public void onClick(View v) {        if (v == mButton) {            performAnimate();        }    }    private static class ViewWrapper {        private View mTarget;        public ViewWrapper(View target) {            mTarget = target;        }        public int getWidth() {            return mTarget.getLayoutParams().width;        }        public void setWidth(int width) {            mTarget.getLayoutParams().width = width;            mTarget.requestLayout();        }    }

The code above increases the width of the Button to PX within 5 S. To achieve this effect, we provide the ViewWrapper class for wrapping the View. In this example, the package Button is used, then we will be familiar with ViewWrapper width for animation, and modify its internal target width in the setWidth method, and the target is actually our packaged Button, this way, you can understand the animation indirectly. The above Code also applies to other attributes of an object. The following figure shows the effect.

OK, the effect is reached, and the width is actually animated.

Use ValueAnimator to listen to the animation process and change the attributes.

First, let's talk about ValueAnimator. ValueAnimator does not act on any object, that is, directly using it has no animation effect. It can animation a value, and then we can listen to its animation process, modify the attribute value of our object during the animation process, which is equivalent to the animation of our object. Still not quite clear? It doesn't matter. The following example shows

Private void incluimate (final View target, final int start, final int end) {ValueAnimator valueAnimator = ValueAnimator. ofInt (1,100); valueAnimator. define (new AnimatorUpdateListener () {// hold an IntEvaluator object to facilitate the following valuation: use private IntEvaluator mEvaluator = new IntEvaluator (); @ Override public void onAnimationUpdate (ValueAnimator animator) {// get the progress value of the current animation, int currentValue = (Integer) animator between Integer and 1-100. getAnimatedValue (); Log. d (TAG, current value: + currentValue); // calculate the ratio of the current progress to the entire animation process. float fraction = currentValue/100f between 0 and 1; // I am lazy here, but why don't I use the ready-made method? // directly call the integer estimator to calculate the width based on the proportion and then set it to the Button target. getLayoutParams (). width = mEvaluator. evaluate (fraction, start, end); target. requestLayout () ;}}); valueAnimator. setDuration (5000 ). start () ;}@ Override public void onClick (View v) {if (v = mButton) {descriimate (mButton, mButton. getWidth (), 500 );}}

The animation of the above Code is the same as that of ViewWrapper. See. Let me talk about this ValueAnimator. For example, it will change the number from 1 to 100 within ms, and then calls back the onAnimationUpdate method for each frame of the animation, in this method, we can obtain the current value (1-100), according to the proportion of the current value (current value/100 ), we can calculate the current width of the Button. For example, if the time is over half, the current value is 50 and the proportion is 0.5. Assume that the start width of the Button is PX, and the final width is PX, the width of the Button should also be half of the total increase width. The total increase width is 500-100 = 400. Therefore, the width of the Button should be increased by 400*0.5 = 200, the current Button width should be the initial width + increase width (100 + 200 = 300 ). The above calculation process is very simple. In fact, it is the internal implementation of the integer valuator IntEvaluator. We don't need to write it by ourselves. Use it directly.

Words written below

So far, the analysis in this article has been basically completed. I want to talk about the following points.

1. The function of View animation (gradient animation) is limited. You can try to use Attribute animation.

2. to use Attribute animation for various Android versions, you need to use nineoldandroids, which is a GitHub open-source project. Both the jar package and the source code can be stored online. If you cannot download the jar package, I can send it to you

3. Complex animations are a reasonable combination of simple animations. In addition, the method described in this article can play an animation effect on any attribute, that is, you can make almost any animation.

4. interpolator and TypeEvaluator in property animation are very important. They are an important means to achieve non-uniform animation. You should try to understand them, and you 'd better customize them.

5. If you can read all my blog posts in this animation series and understand it, I think you are absolutely proficient in animation, and I don't think there are interviewers who can ask you about it.

Related Article

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.