Preface
Android supports native animation, which provides great convenience for application developers to develop beautiful interfaces. Sometimes animation is necessary. When you want to implement a sliding special effect, if you are confused about it, you can consider the animation. Maybe the animation can be done easily. Next we will briefly review the animations in Android. This article will introduce a slightly more complex animation.
Animation category
View animation: Also called gradient animation. It mainly supports translation, rotation, scaling, and transparency for View animations.
Drawable AnimationIt is also called Frame Animation. It mainly sets the View background. You can set multiple backgrounds for the View in the form of animations.
Object Property Animation(New to Android3.0): Animations can be performed on Object Attributes, not just views. The default animation interval is 300 ms, and the default frame rate is 10 ms/frame. The effect can be achieved: During a time interval, the object changes from one property value to another. Therefore, attribute animation is almost omnipotent, as long as the object has this property, it can achieve animation effects, but property animations are available only from Android3.0, which severely restricts the use of property animations. This is the role of the open-source animation library nineoldandroids, which uses nineoldandroids, property animations can be used on systems earlier than 3.0, with the nineoldandroids URL being: http://nineoldandroids.com. When it comes to attribute animation, we have to mention the TimeInterpolator and the TypeEvaluator.
TimeInterpolator and TypeEvaluatorTimeInterpolator are translated as time interpolation. The function of TimeInterpolator is to calculate the percentage of changes in the current attribute value based on the percentage of time elapsed. the preset LinearInterpolator (linear interpolation tool: constant Speed animation), AccelerateDecelerateInterpolator (acceleration and deceleration interpolation: slow and fast between the two ends of the animation) and DecelerateInterpolator (deceleration interpolation: increasingly slow animation); Chinese Translation of TypeEvaluator is a type valuation algorithm, it is used to calculate the changed attribute values based on the percentage of changes in the current attribute. the preset values include IntEvaluator (for integer attributes) and FloatEvaluator (for floating point attributes) and ArgbEvaluator (for the Color attribute ). It may be a bit obscure. It doesn't matter. The following is an example to understand.
Looking at the above animation, it is clear that the above animation is a constant speed animation, which uses a linear interpolation tool and an integer valuation algorithm. Within 40 ms, the x attribute of the View is transformed from 0 to 40, because the animation's default update rate is 10 ms/frame, the animation will be divided into 5 frames. We will consider the third frame (x = 20 t = 20 ms ), when the time t = 20 ms, the percentage of time passing is 0.5 (20/40 = 0.5), which means that the time has passed by half, then how much should x Change, this is determined by the interpolation tool and the valuation algorithm. For linear interpolation, when time passes by half, the transformation of x should be half, that is, the change of x is 0.5. Why? Because it is a linear interpolation tool that implements constant speed animation, let's look at its source code:
public class LinearInterpolator implements Interpolator { public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return input; }}
Obviously, the return value of the linear interpolation tool is the same as the input value. Therefore, the value returned by the interpolation tool is 0.5, which means that the change of x is 0.5. At this time, the work of the interpolation tool is complete.
The specific value of x is determined by the valuation algorithm. Let's look at the source code of the integer valuation algorithm:
public class IntEvaluator implements TypeEvaluator
{ public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int)(startInt + fraction * (endValue - startInt)); }}
The above algorithm is very simple. The three evaluate parameters represent the estimated decimal number, start value, and end value, which correspond to 0.5, and respectively. According to the above algorithm, the result returned by the integer value is 20, which is the origin of (x = 20 t = 20 ms.
Description: Property animation requires the set Method and get method (optional) for the property. In addition to the provided by the system, the interpolation tool and the valuation algorithm can also be customized. The implementation method is also very simple, because the interpolation tool and the valuation algorithm are both interfaces and there is only one internal method, we only need to derive a class implementation interface, and then you can make amazing animation effects. Specifically, the User-Defined interpolation tool must implement Interpolator or TimeInterpolator, and the user-defined valuation algorithm must implement TypeEvaluator. In addition, if you want to animation other types (non-int, float, color), you must customize the type valuation algorithm.
Introduction to nineoldandroids
Its functions are exactly the same as those of Classes in android. animation. *, and they are used in the same way. As long as we use nineoldandroids to write animations, we can run them on all Android systems. The following animation classes are commonly used: ValueAnimator, ObjectAnimator, and AnimatorSet. ObjectAnimator inherits from ValueAnimator, and AnimatorSet is an animation set. You can define an animation group. It is easy to use. Here are some small chestnuts.
Chestnut 1: Change the translationY attribute of an object (myObject) and let it pan a distance up along the Y axis: its height. This animation is completed within the default time, the animation completion time can be defined. For more flexible effects, we can also define interpolation devices and valuation algorithms. However, in general, we do not need to customize the animation, and the system has already been preset, suitable for common animations.
ObjectAnimator.ofFloat(myObject, translationY, -myObject.getHeight()).start();
Chestnut 2: change the background color attribute of an object. A typical scenario is to change the background color of the View. The following animation allows the gradient of the background color from 0xFFFF8080 to 0xff80ff within 3 seconds, in addition, the animation will have infinite loops and will have a reverse effect.
ValueAnimator colorAnim = ObjectAnimator.ofInt(this, backgroundColor, /*Red*/0xFFFF8080, /*Blue*/0xFF8080FF);colorAnim.setDuration(3000);colorAnim.setEvaluator(new ArgbEvaluator());colorAnim.setRepeatCount(ValueAnimator.INFINITE);colorAnim.setRepeatMode(ValueAnimator.REVERSE);colorAnim.start();
Chestnut 3: An animation set. The rotation, translation, scaling, and transparency of the View are all changed within 5 seconds.
AnimatorSet set = new AnimatorSet();set.playTogether( ObjectAnimator.ofFloat(myView, rotationX, 0, 360), ObjectAnimator.ofFloat(myView, rotationY, 0, 180), ObjectAnimator.ofFloat(myView, rotation, 0, -90), ObjectAnimator.ofFloat(myView, translationX, 0, 90), ObjectAnimator.ofFloat(myView, translationY, 0, 90), ObjectAnimator.ofFloat(myView, scaleX, 1, 1.5f), ObjectAnimator.ofFloat(myView, scaleY, 1, 0.5f), ObjectAnimator.ofFloat(myView, alpha, 1, 0.25f, 1));set.setDuration(5 * 1000).start();
Chestnut 4: The following is a simple call method. Its animate method is unique to nineoldandroids.
Button myButton = (Button)findViewById(R.id.myButton);//Note: in order to use the ViewPropertyAnimator like this add the following import:// import static com.nineoldandroids.view.ViewPropertyAnimator.animate;animate(myButton).setDuration(2000).rotationYBy(720).x(100).y(100);
Chestnut 5: an animation of slightly complex points implemented using nineoldandroids
The layout xml is as follows:
<framelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"></framelayout>
The Code is as follows:
Public class MainActivity extends Activity implements OnClickListener {private static final String TAG = MainActivity; private Button listener; private Button mItemButton1; private Button mItemButton2; private Button mItemButton3; private Button mItemButton4; private Button mItemButton5; private boolean mIsMenuOpen = false; @ Override protected void onCreate (Bundle savedInstanceState) {super. on Create (savedInstanceState); setContentView (R. layout. activity_main); initView () ;}@ TargetApi (Build. VERSION_CODES.HONEYCOMB) private void initView () {mMenuButton = (Button) findViewById (R. id. menu); mMenuButton. setOnClickListener (this); mItemButton1 = (Button) findViewById (R. id. item1); mItemButton1.setOnClickListener (this); mItemButton2 = (Button) findViewById (R. id. item2); mItemButton2.setOnClickLi Stener (this); mItemButton3 = (Button) findViewById (R. id. item3); mItemButton3.setOnClickListener (this); mItemButton4 = (Button) findViewById (R. id. item4); mItemButton4.setOnClickListener (this); mItemButton5 = (Button) findViewById (R. id. item5); mItemButton5.setOnClickListener (this) ;}@ Override public boolean onCreateOptionsMenu (Menu menu) {mMenuButton. optional mclick (); getMenuInflater (). inflate (R. men U. main, menu); return false ;}@ Override public void onClick (View v) {if (v = mMenuButton) {if (! MIsMenuOpen) {mIsMenuOpen = true; doAnimateOpen (bytes, 0, 5,300); doAnimateOpen (mItemButton2, 1, 5,300); doAnimateOpen (mItemButton3, 2, 5,300); doAnimateOpen, 5,300); doAnimateOpen (mItemButton5, 4, 5,300);} else {mIsMenuOpen = false; doAnimateClose (mItemButton1, 0, 5,300); doAnimateClose (mItemButton2, 1, 5,300 ); doAnimateClose (mItemButton3, 2, 5,300); doAnimateClos E (mItemButton4, 3, 5,300); doAnimateClose (mItemButton5, 4, 5,300) ;}} else {Toast. makeText (this, you clicked + v, Toast. LENGTH_SHORT ). show ();}} /*** open the menu animation * @ param view: Execute the animation view * @ param index view sequence in the animation sequence * @ param total number of animation sequences * @ param radius animation radius */private void doAnimateOpen (View view, int index, int total, int radius) {if (view. getVisibility ()! = View. VISIBLE) {view. setVisibility (View. VISIBLE);} double degree = Math. PI * index/(total-1) * 2); int translationX = (int) (radius * Math. cos (degree); int translationY = (int) (radius * Math. sin (degree); Log. d (TAG, String. format (degree = % f, translationX = % d, translationY = % d, degree, translationX, translationY); AnimatorSet set = new AnimatorSet (); // contains the animation set for translation, scaling, and transparency. playTogether (ObjectA Nimator. ofFloat (view, translationX, 0, translationX), ObjectAnimator. ofFloat (view, translationY, 0, translationY), ObjectAnimator. ofFloat (view, scaleX, 0f, 1f), ObjectAnimator. ofFloat (view, scaleY, 0f, 1f), ObjectAnimator. ofFloat (view, alpha, 0f, 1); // set the animation period to 500 ms. setDuration (1*500 ). start ();} /*** close the menu animation * @ param view: view where the animation is executed * @ param index view sequence in the animation sequence * @ param total number of animation sequences * @ param Radius animation radius */private void doAnimateClose (final View view, int index, int total, int radius) {if (view. getVisibility ()! = View. VISIBLE) {view. setVisibility (View. VISIBLE);} double degree = Math. PI * index/(total-1) * 2); int translationX = (int) (radius * Math. cos (degree); int translationY = (int) (radius * Math. sin (degree); Log. d (TAG, String. format (degree = % f, translationX = % d, translationY = % d, degree, translationX, translationY); AnimatorSet set = new AnimatorSet (); // contains the animation set for translation, scaling, and transparency. playTogether (ObjectAnimator. ofFloat (view, translationX, translationX, 0), ObjectAnimator. ofFloat (view, translationY, translationY, 0), ObjectAnimator. ofFloat (view, scaleX, 1f, 0f), ObjectAnimator. ofFloat (view, scaleY, 1f, 0f), ObjectAnimator. ofFloat (view, alpha, 1f, 0f); // adds event listening to the animation. When the animation ends, we hide the current view set. addListener (new AnimatorListener () {@ Override public void onAnimationStart (Animator animator) {}@ Override public void Merge (Animator animator) {view. setVisibility (View. GONE) ;}@ Override public void onAnimationCancel (Animator animator) {}}); set. setDuration (1*500 ). start ();}}