"Go" Android Android properties animation in-depth analysis

Source: Internet
Author: User

Reprint Please specify source:http://blog.csdn.net/singwhatiwanna/article/details/17841165

begins

Like design patterns, we also ask a question to elicit our content.

Questions:

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

You may say, this is very simple, with the gradient animation can be done, we can try, can you write it? Soon you will suddenly realize that the gradient animation does not support the animation of the width at all, yes, the gradient animation only supports four types: Pan (Translate), rotation (Rotate), scale, opacity (Alpha). Of course you zoom in X (ScaleX) to make the button zoom in the x direction, it looks as if the width is increased, not really, just the button is magnified, and because only in the x direction is magnified, this time the button background and the above text is stretched, It's even possible that the button will go beyond the screen. Below is

The above effect is obviously very poor, and it is not really the width of the animation, but fortunately we also have property animation, we use property animation to try

See Demo

1     Private voidperformanimate () {2Objectanimator.ofint (Mbutton, "width",). Setduration (5000). Start ();3     }4 5 @Override6      Public voidOnClick (View v) {7         if(v = =Mbutton) {8 performanimate ();9         }Ten}

The above code to run a bit found no effect, in fact, no effect is right, if you casually pass a property in the past, light is not animated, heavy program directly crash.

For the above example, if you set the Android:width and android:height of the button to wrap_content in the XML file, you have an effect on android: Width and android:height are set to a specific value (100DP, etc.) that will have no effect.

The following analysis of the principle of property animation:

Property animations require an animated object to provide a get and set method for the property, which, based on the familiar initial and final values that you pass, invokes the set method multiple times with the effect of the animation, and each time the value passed to the set method is different, which is exactly over time, The values passed are getting closer to the final value. To summarize, you animate the property xxx of object, and if you want the animation to take effect, you need to satisfy two conditions at the same time:

1. Object must provide the Setxxx method, if the animation does not pass the initial value, then also provide the GetXXX method, because the system to get the initial value of the XXX property (if this is not satisfied, the program directly crash)

2. Object setxxx changes to attribute xxx must be able to be reflected in some way, such as what will bring about UI changes (if this is not satisfied, the animation is ineffective but not crash)

The above conditions are indispensable

So why do we animate the Width property of the button without effect? This is because the button interior provides the getwidth and SetWidth methods, but this setwidth method is not to change the size of the view, it is a new method TextView added, view is not the SetWidth method, Because the button inherits the TextView, the button also has the SetWidth method. Here's a look at the source code for this getwidth and SetWidth method:

1     /**2 * Makes the TextView exactly this many pixels wide.3 * You could does the same thing by specifying this number in the4 * Layoutparams.5      *6      * @see#setMaxWidth (int)7      * @see#setMinWidth (int)8      * @see#getMinWidth ()9      * @see#getMaxWidth ()Ten      * One * @attr ref Android. R.styleable#textview_width A      */ - @android. View.remotableviewmethod -      Public voidSetWidth (intpixels) { theMmaxwidth = Mminwidth =pixels; -Mmaxwidthmode = Mminwidthmode =PIXELS; -  - requestlayout (); + invalidate (); -     } +  A     /** at * Return The width of the your view. -      * -      * @returnthe width of your view, in pixels. -      */ -@ViewDebug. Exportedproperty (category = "Layout") -      Public Final intgetwidth () { in         returnMright-Mleft; -}

From the source can be seen, getwidth really is to get the width of the view, and SetWidth is TextView and its subclasses of the exclusive method, it does not set the width of the view, but set the maximum width of the textview and the minimum width, The width of this and textview is not a thing, specifically, the width of the textview corresponds to the Android:layout_width attribute in the XML, and TextView has an attribute android:width, this android: The Width property corresponds to the SetWidth method of the TextView. OK, I admit that this paragraph of my description is a bit confusing, but the thing is really this way, and I have not found this android:width attribute has any important use, feel like useless, here do not delve into, or deviate from the subject. In short, TextView and button setwidth and getwidth do not do the same thing, through the setwidth can not change the width of the control, so the width of the property animation has no effect, corresponding to the property animation of the two conditions, The reason the animation does not take effect in this example is that condition 1 does not meet the condition 2.

In response to these questions, Google tells us there are 3 solutions:

1. Add the Get and set methods to your object, if you have permission

2. Wrapping the original object with a class, indirectly providing it with get and set methods

3. Use Valueanimator, monitor the animation process, the implementation of their own property changes

It looks a little abstract, but don't worry, I'll introduce you here.

Animate any property

For the three solutions presented above, here is a detailed description:

Add the Get and set methods to your object, if you have permission.

The meaning of this is very good understanding, if you have permission, plus get and set will be done, but many times we do not have the authority to do so, such as the question at the beginning of this article, you can not add a compliant SetWidth method, because this is the Android implemented within the SDK. This method is the simplest, but often not feasible, and there is no more analysis of it.

wraps the original object with a class, providing it with the get and set methods indirectly

This is a very useful solution, is my favorite, because it is very convenient to use, but also very good understanding, the following will be a concrete example to introduce it

1     Private voidperformanimate () {2Viewwrapper wrapper =NewViewwrapper (Mbutton);3Objectanimator.ofint (Wrapper, "width",). Setduration (5000). Start ();4     }5 6 @Override7      Public voidOnClick (View v) {8         if(v = =Mbutton) {9 performanimate ();Ten         } One     } A  -     Private Static classViewwrapper { -         PrivateView Mtarget; the  -          PublicViewwrapper (View target) { -Mtarget =Target; -         } +  -          Public intgetwidth () { +             returnmtarget.getlayoutparams (). width; A         } at  -          Public voidSetWidth (intwidth) { -Mtarget.getlayoutparams (). width =width; - mtarget.requestlayout (); -         } -}

In the above code 5s to increase the width of the button to 500px, in order to achieve this effect, we provide the Viewwrapper class specifically for packaging view, specifically to this example is the wrapper button, and then we are familiar with the width of viewwrapper to do animation, And it modifies the width of the target inside the SetWidth method, and target is actually the button that we wrapped, so an indirect property animation is done. The code above also applies to other properties of an object. See the effect below

The result of the above code might be that the button flashes first to 500px length, and then slowly changes, this is because the Objectanimator does not set the start value of the button change. will be objectanimator.ofint (wrapper, "width",). Setduration (). Start ();

Change to Objectanimator.ofint (wrapper, "width", btn.getwidth (), and () Setduration (). Start (); just fine.


OK, the effect achieved, the real realization of the width of the animation.

using Valueanimator, listening to the animation process, the implementation of their own property changes

The first thing to say is that Valueanimator,valueanimator itself does not work for any object, that is, using it directly without any animated effect. It can animate a value, and then we can listen to its animation process and modify the property values of our objects during the animation, which is equivalent to animating our objects. Still don't understand? That's okay, here's an example.

1     Private voidPerformanimate (FinalView Target,Final intStartFinal intend) {2Valueanimator valueanimator = valueanimator.ofint (1, 100);3 4Valueanimator.addupdatelistener (NewAnimatorupdatelistener () {5 6             //hold a Intevaluator object to use when estimating below7             PrivateIntevaluator Mevaluator =Newintevaluator ();8 9 @OverrideTen              Public voidOnanimationupdate (Valueanimator animator) { One                 //gets the current animation's progress value, Integer, 1-100 A                 intCurrentValue =(Integer) animator.getanimatedvalue (); -LOG.D (TAG, "Current value:" +currentvalue); -  the                 //calculates the ratio of current progress to the entire animation process, floating-point, 0-1 -                 floatfraction = CurrentValue/100f; -  -                 //I'm lazy here, but there's a ready-made one . +                 //directly call an integer estimator to calculate the width by scale, and then set it to the button -Target.getlayoutparams (). width =mevaluator.evaluate (fraction, start, end); + target.requestlayout (); A             } at         }); -  -Valueanimator.setduration (5000). Start (); -     } -  - @Override in      Public voidOnClick (View v) { -         if(v = =Mbutton) { toPerformanimate (Mbutton, Mbutton.getwidth (), 500); +         } -}

The animation of the above code is the same as using Viewwrapper, please see. About this valueanimator I'm going to say again, for example, it will change a number from 1 to 100 within 5000ms, then each frame of the animation will callback the Onanimationupdate method, in which we can get the current value (1-100), Based on the current value of the ratio (current value/100), we can calculate the button now the width should be how much, such as time is over half, the current value is 50, the ratio is 0.5, assuming that the button's starting width is 100px, the final width is 500px, Then the width of the button increase should also account for half of the total increase in width, the total increase width is 500-100=400, so this time the button should increase the width of 400*0.5=200, then the width of the current button should be the initial width + increase width (100+200= 300). The above calculation process is very simple, in fact, it is the integral type Estimator Intevaluator internal implementation, all we do not have to write, directly use it.

write it in the back.

So far, the analysis of this article is basically complete, there are a few points I would like to say again.

1.View animations (gradient animations) are limited, and you can try using property animations

2. In order to use attribute animation on various Android versions, you need to adopt Nineoldandroids, which is GitHub open source project, jar package and source code can be online to, if not the jar package, I can send everyone

3. Complex animations are a reasonable combination of simple animations, plus the method described in this article, you can animate any property, meaning you can almost make any animation

4. The Interpolator (interpolator) and estimator (Typeevaluator) in the property animationis important, it is an important means to achieve the non-uniform animation, you should try to understand it, it is best that you can also customize them

"Go" Android Android properties animation in-depth analysis

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.