Advanced usage of Valueanimator and objectanimator for full parsing (medium) of Android property animations

Source: Internet
Author: User
Tags gety

Reprint Please specify source: http://blog.csdn.net/guolin_blog/article/details/43536355

Hello everyone, in the last article, we learned the basic usage of Android properties animation, and of course, some of the most commonly used usage, which is enough to cover the animation needs of most of our usual situations. However, as mentioned in the previous article, the property animation has greatly improved the motion tween, the property animation can be done before the motion tween could do, the animation can not be done by the animation of the current property is also possible to do. So today we're going to take a look at the advanced usage of property animations and see how some of the features that can be implemented by tweened animations are realized.

Reading this article requires you to have a certain understanding of property animation, and master the basic use of property animation, if you also do not understand the property animation, it is recommended to read the Android property animation fully resolved (above), the basic use of the initial knowledge of property animation .

Advanced usage of Valueanimator

As mentioned in the previous article about the shortcomings of motion tweens, tweened animations can only animate view objects. The property animation is no longer subject to this restriction, and it can animate any object. So you should remember one of the examples I gave in the previous article, for example, we have a custom view in which a point object is used to manage coordinates, and then in the OnDraw () method, it is plotted based on the coordinate value of the point object. That is, if we can animate the point object, the entire custom view will have an animated effect. OK, let's learn how to achieve this effect.

Before we start, we also need to grasp another point of knowledge, that is, the use of typeevaluator. It's possible that in most cases we don't use typeevaluator when using property animations, but you should also look at how it's used to prevent a solution that comes to mind when we're faced with some sort of problem that can't be solved.

So what is the role of Typeevaluator? In simple terms, it tells the animation system how to overdo the value from its initial value to its end. The Valueanimator.offloat () method we learned in the previous article was to achieve a smoothing over between the initial and the end values, so how does this smoothing work? In fact, the system has a built-in floatevaluator, it is calculated to tell the animation system how to from the initial value to the end value, we look at the Floatevaluator code implementation:

public class Floatevaluator implements Typeevaluator {public    Object evaluate (float fraction, Object startvalue, Obje CT endvalue) {        float startfloat = ((number) startvalue). Floatvalue ();        return startfloat + fraction * ((number) endvalue). Floatvalue ()-startfloat);}    }
As you can see, Floatevaluator implements the Typeevaluator interface and then overrides the Evaluate () method. Evaluate () method passed three parameters, the first parameter fraction is very important, this parameter is used to indicate the completion of the animation, we should be based on it to calculate the current animation value should be how much, the second third parameter represents the animation's initial value and the end value respectively. Then the logic of the above code is clearer, with the end value minus the initial value, calculate the difference between them, and then multiplied by the coefficient of fraction, plus the initial value, then the current animation value.

OK, that Floatevaluator is the system built-in good function, do not need us to write, but the introduction of its implementation is to pave the way for the function behind us. We used Valueanimator's offloat () and Ofint () methods, respectively, to animate the data of floating-point and integer types, but there is actually a ofobject () method in Valueanimator. is used to animate an arbitrary object. However, the animation of objects is significantly more complicated than floating-point or integer data, because the system will not know how to get from the initial object to the end object at all, so we need to implement a typeevaluator to tell the system how to overdo it.

The following is a first definition of a point class, as follows:

public class Point {    private float x;    private float y;    Public point (float x, float y) {        this.x = x;        This.y = y;    }    public float GetX () {        return x;    }    public float GetY () {        return y;    }}

The point class is very simple, with only X and y two variables used to record the position of coordinates and provides a construction method to set the coordinates, as well as a get method to get the coordinates. Next, define the Pointevaluator as follows:

public class Pointevaluator implements typeevaluator{    @Override public    Object Evaluate (float fraction, object Startvalue, Object endvalue) {point        StartPoint = (point) startvalue;        Point endPoint = (point) endvalue;        float x = startpoint.getx () + fraction * (Endpoint.getx ()-startpoint.getx ());        Float y = startpoint.gety () + fraction * (endpoint.gety ()-startpoint.gety ());        Point point = new Point (x, y);        return point;    }}
As you can see, Pointevaluator also implements the Typeevaluator interface and re-writes the Evaluate () method. In fact, the logic in the Evaluate () method is very simple, first turning the startvalue and endvalue into a point object, and then also calculating the values of x and y of the current animation according to Fraction, and finally assembling into a new point object and returning.

So we can write the pointevaluator, and then we'll be able to animate the point object very easily, say we have two point objects, now we need to smooth the Point1 through the animation to Point2, we can write:

Point point1 = new Point (0, 0); Point point2 = new Point (300, 300); Valueanimator anim = valueanimator.ofobject (New Pointevaluator (), point1, Point2); Anim.setduration (Anim.start); );
The code is simple, and here we have a new two point object and set their coordinate points in the constructor. Then call Valueanimator's Ofobject () method to build an instance of Valueanimator, and it is important to note that the Ofobject () method requires more than one typeevaluator parameter to be passed in. Here we just need to pass in an instance of the pointevaluator that we just defined.

Well, that's all the use of custom typeevaluator, and with this knowledge, we can try to animate the entire custom view by animating the point object.

Create a new myanimview inherit from view, the code looks like this:

public class Myanimview extends View {public static final float RADIUS = 50f;    Private point Currentpoint;    Private Paint Mpaint;        Public Myanimview (context context, AttributeSet Attrs) {Super (context, attrs);        Mpaint = new Paint (Paint.anti_alias_flag);    Mpaint.setcolor (Color.Blue); } @Override protected void OnDraw (canvas canvas) {if (currentpoint = = null) {currentpoint = new            Point (radius, radius);            Drawcircle (canvas);        Startanimation ();        } else {drawcircle (canvas);        }} private void Drawcircle (canvas canvas) {Float x = Currentpoint.getx ();        Float y = currentpoint.gety ();    Canvas.drawcircle (x, Y, RADIUS, mpaint);        } private void Startanimation () {Point startPoint = new Point (radius, radius);        Point endPoint = new Point (getwidth ()-Radius, getheight ()-radius); Valueanimator anim = valueanimator.ofobject (New Pointevaluator (), startPoint, EndPoint); Anim.addupdatelistener (New Valueanimator.animatorupdatelistener () {@Override public void Onanimatio                Nupdate (Valueanimator animation) {currentpoint = (point) animation.getanimatedvalue ();            Invalidate ();        }        });        Anim.setduration (5000);    Anim.start (); }}
It's basically simple, and there's not a few lines of code in total. First, a Paint object is initialized as a brush in the constructor of the custom view, the brush color is set to blue, and then it is drawn in the OnDraw () method. The logic we draw here is controlled by the Currentpoint object, and if the Currentpoint object is not equal to NULL, then call the Drawcircle () method to draw a circle with a radius of 50 at the coordinates of the currentpoint. If the Currentpoint object is empty, then call the Startanimation () method to start the animation.

So let's take a look at the code in the Startanimation () method, in fact, we should be familiar with, that is, the point object is an animation operation. Here we define a startpoint and a endpoint, which are the upper-left and lower-right corners of the view, respectively, and set the duration of the animation to 5 seconds. And then one thing that needs attention is that we listen to the process of the animation through the listener and callback the Onanimationupdate () method whenever the point value changes. In this method, we re-assign the Currentpoint object and call the Invalidate () method so that the OnDraw () method is called again, and because the coordinates of the Currentpoint object have changed, Then the position of the drawing will also change, so a translation of the animation effect is realized.

Here we just need to introduce this custom control into the layout file:

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"    android:layout_width= "Match_ Parent "    android:layout_height=" match_parent "    >    <com.example.tony.myapplication.myanimview        android:layout_width= "match_parent"        android:layout_height= "Match_parent"/></relativelayout>

Finally run the program, as shown in the following:


Ok! This allows us to successfully implement the function of animating the object by value manipulation, which is the advanced usage of valueanimator.

Advanced usage of Objectanimator

The basic usage and working principle of objectanimator have been explained in the previous article, I believe everyone has mastered it. So we should all remember, we in the spat tween animation when it is mentioned that the tweened animation can only achieve the movement, scaling, rotation and fade out of the four animation operations, the function is limited to death is these, basically there is no extensibility to speak of. For example, if we want to make a dynamic change in the color of the view, there is no way to animate the motion.

But the property animation will not be limited by these rules, it is very extensible, for the dynamic change the color of the view of the function is completely competent, then we will learn how to achieve this effect.

It should be remembered that the internal mechanism of objectanimator is to realize the animation effect by looking for the get and set methods of the specific attributes, and then changing the values continuously through the method. So we need to define a color property in Myanimview and provide its get and set methods. Here we can set the Color property to a string type, using the format of #rrggbb to represent the colour value, as shown in the code below:

public class Myanimview extends View {... private string Color;public string GetColor () {return color;} public void SetColor (String color) {This.color = Color;mpaint.setcolor (Color.parsecolor (color)); invalidate ();} ...}
Note in the SetColor () method, we have written a very simple logic, which is to set the color of the brush to the color passed in by the method parameter, and then call the Invalidate () method. Although this code has only three rows, it does a very central function of refreshing the view immediately after changing the brush color, and then the OnDraw () method is called. The OnDraw () method is drawn according to the color of the current brush, so that the color changes dynamically.

So the next question is how to get the SetColor () method to be called, without a doubt, of course, with the help of the Objectanimator class, but we have to do a very important job before using Objectanimator. is to write a typeevaluator that tells the system how to make the color over. Create the Colorevaluator and implement the Typeevaluator interface, as shown in the following code:

public class Colorevaluator implements Typeevaluator {private int mcurrentred = -1;private int mcurrentgreen = -1;private int mcurrentblue = 1; @Overridepublic object evaluate (float fraction, object Startvalue, Object endvalue) {String Startcol or = (String) startvalue; String endcolor = (string) endvalue;int startred = Integer.parseint (startcolor.substring (1, 3), +); int startgreen = Integ Er.parseint (Startcolor.substring (3, 5), int startblue = Integer.parseint (startcolor.substring (5, 7), +); int endred = Integer.parseint (endcolor.substring (1, 3), int endgreen = Integer.parseint (endcolor.substring (3, 5), 16); int endblue = Integer.parseint (endcolor.substring (5, 7), 16);//Initialize the value of the color if (mcurrentred = =-1) {mcurrentred = startred;} if (Mcurrentgreen = =-1) {mcurrentgreen = Startgreen;} if (Mcurrentblue = =-1) {mcurrentblue = Startblue;} Calculates the difference between the initial color and the ending color int reddiff = Math.Abs (startred-endred); int greendiff = Math.Abs (startgreen-endgreen); int Bluediff = Math.Abs (Startblue-endblue);int Colordiff = Reddiff + Greendiff + bluediff;if (mcurrentred! = endred) {mcurrentred = Getcurrentcolor (startRed, EndRed, Colordiff, 0,fraction);}  else if (mcurrentgreen! = endgreen) {Mcurrentgreen = Getcurrentcolor (Startgreen, Endgreen, Colordiff,reddiff, fraction);} else if (mcurrentblue! = endblue) {mcurrentblue = Getcurrentcolor (Startblue, Endblue, Colordiff,reddiff + GreenDiff, frac tion);} The computed value of the current color assembly returns string currentcolor = "#" + gethexstring (mcurrentred) + gethexstring (mcurrentgreen) + gethexstring ( Mcurrentblue); return currentcolor;} /** * Calculates the current color based on the fraction value.  */private int Getcurrentcolor (int startcolor, int endcolor, int colordiff,int offset, float fraction) {int currentcolor;if (StartColor > EndColor) {currentcolor = (int) (StartColor-(fraction * colordiff-offset)); if (CurrentColor < EndColor) {CurrentColor = EndCo Lor;}} else {currentcolor = (int) (StartColor + (fraction * colordiff-offset)); if (CurrentColor > EndColor) {currentcolor = EndColor;}} Return CurreNtcolor;} /** * Converts 10 binary color values to 16 binary. */private string gethexstring (int value) {String hexstring = integer.tohexstring (value); if (hexstring.length () = = 1) {hex String = "0" + hexstring;} return hexstring;}}
This is probably the most complex class of our entire animation operation. Yes, the most technical content in advanced usage of attribute animations is how to write a suitable typeevaluator. Fortunately, just now we have written a pointevaluator, to its basic working principle has already had the understanding, then here we mainly study the colorevaluator logic flow.

First, in the Evaluate () method to get the initial and end values of the color, and by the way the string interception of color into the RGB three parts, and the value of RGB converted to decimal digits, then the value of each color range is 0-255. Next calculate the initial color value to the end of the difference between the color value, this difference is very important, determines the speed of the color change, if the initial color value and the end color value is very similar, then the color changes will be relatively slow, and if the color values vary greatly, for example, from black to white, then going through 255* 3 The color of this amplitude is too much, the change will be very fast.

The speed at which the color changes are controlled is achieved by Getcurrentcolor (), which calculates the current fraction value to what color it should be, and where the change speed is controlled based on the initial and final color difference. Finally, the calculated color is returned.

Finally, since the color we calculate is a decimal number, it is also necessary to call the Gethexstring () method to convert them to a hexadecimal string, then assemble the RGB colors and return them as the final result.

Well, after Colorevaluator wrote, we finished the most complicated work, and the rest was a few simple calls, for example, we want to achieve the animation from blue to red over 5 seconds, you can write:

Objectanimator anim = Objectanimator.ofobject (Myanimview, "color", new Colorevaluator (), "#0000FF", "#FF0000"); Anim.setduration (Anim.start);
The usage is very easy to understand, I believe I do not need to explain.

Next we need to move the above piece of code into the Myanimview class so that it can be combined with just the point motion animation to play together, and this is going to take advantage of the combination animation technology we learned in the previous article. Modify the code in the Myanimview as follows:

public Class Myanimview extends View {... private void startanimation () {Point startPoint = new Point (RADIUS, RADI        US);        Point endPoint = new Point (getwidth ()-Radius, getheight ()-radius);        Valueanimator anim = valueanimator.ofobject (New Pointevaluator (), StartPoint, endPoint); Anim.addupdatelistener (New Valueanimator.animatorupdatelistener () {@Override public void Onanimatio                Nupdate (Valueanimator animation) {currentpoint = (point) animation.getanimatedvalue ();            Invalidate ();        }        });        Objectanimator anim2 = Objectanimator.ofobject (This, "color", new Colorevaluator (), "#0000FF", "#FF0000");        Animatorset animset = new Animatorset ();        Animset.play (Anim). with (ANIM2);        Animset.setduration (5000);    Animset.start (); }}
As you can see, we haven't changed too much of the code, and the emphasis has just been on modifying parts of the Startanimation () method. This first moves the over-color code logic into the Startanimation () method, noting that the code itself is executed in Myanimview, so Objectanimator.ofobject () The first parameter is passed directly to this one. We then created a animatorset and set two animations to play simultaneously, with an animated duration of five seconds and the last animation. Now run the code again, as shown in the following:


OK, the position animation and the color animation are very harmonious together, it seems that the effect is quite good, so we have objectanimator advanced usage also mastered.

Well, through the study of this article, we have a very deep understanding of the property animation, then the content of this article to this end, the next article will introduce more about property animation, other tips, please look forward to.

First time to get blog update reminders, as well as more technical information sharing, welcome to follow my public number, sweep the QR code below or search number Guolin_blog, you can pay attention to.

Advanced usage of Valueanimator and objectanimator for full parsing (medium) of Android property animations

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.