In Android, animation can be divided into three kinds, namely, tween animation, frame animation and attribute animation. Next, the use of these three kinds of animation will be introduced in detail.

First, tween animation

Tween animation is also called View animation, so its action object can only be View, it has four typical transformation effects, respectively: translation animation, zoom animation, rotation animation, transparency animation. These four animation effects can be created dynamically through Java code or through XML files. The TranslateAnimation class is used to create a TranslateAnimation. There are two commonly used constructors:

public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
    }Copy the code
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
            int fromYType, float fromYValue, int toYType, float toYValue) {
    }Copy the code

For the first constructor, the arguments fromXDelta and toXDelta represent the starting and ending values of the x shift, in pixels. If toXDelta minus fromXDelta is greater than 0, the View moves right, otherwise it moves left. If the difference is greater than 0, view will move down; otherwise, view will move up. To move a View 100 pixels to the right, do this:

TranslateAnimation translateAnimation = new TranslateAnimation(0f, 0f, 0f, 100f); translateAnimation.setDuration(2000); / / animation duration, translateAnimation unit milliseconds. SetFillAfter (true); View. startAnimation(translateAnimation); // Start animationCopy the code

In the x direction, fromXType and toXType have three types: RELATIVE_TO_SELF and animation.relative_to_parent, representing ABSOLUTE pixels, relative to itself, relative to the parent View, respectively. FromXValue and toXValue. When type is animation. ABSOLUTE, these two values are specific pixel values. When type is animation. RELATIVE_TO_SELF or animation. RELATIVE_TO_PARENT, these two values are proportional values. The values range from 0F to 1.0F, and are the same in the y direction. The specific usage is as follows:

TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f, RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, -1.0f); translateAnimation.setDuration(2000); translateAnimation.setFillAfter(true); view.startAnimation(translateAnimation);Copy the code

RELATIVE_TO_SELF and toYValue is -1.0F (100%). Then the view will move up by its own height, which is a common hidden title effect. When type is set to animation.relative_to_parent, the view moves up the parent view height distance. ScaleAnimation is implemented through the class ScaleAnimation. Constructors are commonly used as follows:

public ScaleAnimation(float fromX, float toX, float fromY, float toY,
            int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {
    }Copy the code

In the x direction, the arguments fromX and toX represent the start and end of the horizontal scaling of the view, respectively. Both are floating point numbers greater than or equal to 0. RELATIVE_TO_SELF, and animation.relative_to_parent. PivotXValue represents the center of the zoom. It can be a specific pixel value or a ratio value. The range of the ratio value is [0f, 1.0f]. The ratio value is commonly used, and the same is true in the Y direction. Specific usage is as follows:

ScaleAnimation ScaleAnimation = new ScaleAnimation(1.0f, 2f, 1.0f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation. RELATIVE_TO_SELF, 0.5 f); scaleAnimation.setDuration(2000); scaleAnimation.setFillAfter(true); view.startAnimation(scaleAnimation);Copy the code

Compared with its own center, the view is stretched twice in the X direction and shrunk by 0.5 times in the Y direction. RotateAnimation is implemented by RotateAnimation. Constructors are commonly used as follows:

public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
            int pivotYType, float pivotYValue) {
    }Copy the code

The fromDegrees and toDegrees parameters represent the starting and ending angles of rotation. PivotXValue and pivotYValue represent the center of rotation. They can be absolute pixel values or proportional values ranging from [0f, 1.0f]. PivotXType and pivotYType represent rotation types. There are three types: animation. ABSOLUTE, animation. RELATIVE_TO_SELF, and animation. RELATIVE_TO_PARENT.

RotateAnimation RotateAnimation = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation. RELATIVE_TO_SELF, 0.5 f); rotateAnimation.setDuration(2000); rotateAnimation.setFillAfter(true); view.startAnimation(rotateAnimation);Copy the code

Realize view relative to its center, instantaneous rotation 360 degrees. Transparency animation is realized by the AlphaAnimation class, and the constructor is as follows:

public AlphaAnimation(float fromAlpha, float toAlpha) {
    }Copy the code

Parameters fromAlpha and toAlpha represent the start and end values of transparency, 0f represents full transparency, and 1.0f represents no transparency. Specific usage is as follows:

AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
        alphaAnimation.setDuration(2000);
        alphaAnimation.setFillAfter(true);
        view.startAnimation(alphaAnimation);Copy the code

Realize the view from no transparency to fully transparent change. View animations are created using the AnimationSet class.

AnimationSet animationSet = new AnimationSet(true); RotateAnimation RotateAnimation = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation. RELATIVE_TO_SELF, 0.5 f); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); animationSet.addAnimation(rotateAnimation); animationSet.addAnimation(alphaAnimation); animationSet.setFillAfter(true); animationSet.setDuration(2000); view.startAnimation(animationSet);Copy the code

An AnimationSet parameter of true means that the combined animation has a common interpolator. What is an interpolator? Is the animation speed variation, the commonly used interpolation is as follows: LinearInterpolator: uniform AccelerateInterpolator: accelerate AccelerateDecelerateInterpolator: Deceleration first acceleration then deceleration Activity BounceInterpolator damping falling, which BounceInterpolator stops several times, can be used in the following way

RotateAnimation RotateAnimation = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation. RELATIVE_TO_SELF, 0.5 f); rotateAnimation.setDuration(2000); rotateAnimation.setFillAfter(true); rotateAnimation.setInterpolator(new AccelerateInterpolator()); view.startAnimation(rotateAnimation);Copy the code

Finally, you can use setRepeatCount() and setRepeatMode() to set the number of times the Animation repeats, and the repeat modes, including animation.restart and animation.reverse, that is, RESTART and REVERSE playback. If you want to listen to the animation, you can use the following interface:

Public static interface AnimationListener {// start void onAnimationStart(Animation Animation); Void onAnimationEnd(Animation Animation); // void onAnimationRepeat(Animation Animation); }Copy the code

2. To implement the XML file in XML mode, place the XML file in the ANim folder under the RES directory. 2.1 Pan animation is realized through labels. To achieve View upward translation of its height distance, that is, title hiding effect:


Copy the code

Move the View up 50 pixels


Copy the code

2.2 Zooming animation is achieved through labels. Realize that the View is stretched twice in the x direction and shrunk 0.5 times in the Y direction relative to its center:


Copy the code

2.3 Rotation animation is realized through labels. To achieve the View relative to its center, instantaneous rotation 360 degrees, while the reverse repeat twice:

Copy the code

2.4 Transparency animation is realized through labels. The View transparency changes from 1.0F to 0F, and the change is accelerated:


Copy the code

The combined animation of 2.5 View was realized by label, but the sequence could not be controlled and could only happen at the same time. It was found in the test that repeatCount was invalid at this time.



    

    

    

    
Copy the code

To implement it in XML mode, loadAnimation() first loads the XML file as follows:

Animation animation = AnimationUtils.loadAnimation(context, R.anim.set_anim);
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }
            @Override
            public void onAnimationEnd(Animation animation) {
            }
            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        view.startAnimation(animation);Copy the code

For example, the panning effect can only change the display effect of the View, but cannot change the real position of the View. For example, if a Button with a click event is moved from the upper left corner of the screen to the upper right corner of the screen, Click the button in the upper right corner and find that it does not respond to the click event. Then click the button in the upper left corner of the screen and there is a response. And tween animation can only work on View, if we want to animate a View object, it is powerless, because of various functional defects, Android 3.0 version introduced property animation to further improve Android animation mechanism.

Second, property animation

With property animation, we can animate a Point object from (0, 0) position to (100, 100) position, in addition to the basic operations of pan, scale, rotate, and transparency of the View. However, there is one caveat: attribute animations only work on Android3.0 or higher. If you want to work with Android3.0 or higher, you can use the JakeWharton animation library: Nineoldandroids.com/, but this library under Android3.0 property animation is actually the traditional tween animation oh! The two core classes in the property animation are ValueAnimator and ObjectAnimator. Let’s look at them one by one.

ValueAnimator is used to calculate the transition between the initial and end values of the animation properties. It is similar to a number generator. For example, if we want to achieve the transition from 0 to 2 and then to 0 in 2000 milliseconds, we can do this:

ValueAnimator animator = ValueAnimator.ofFloat(0f, 2f, 0f); / / set the listener animator. AddUpdateListener (new ValueAnimator. AnimatorUpdateListener () {@ Override public void onAnimationUpdate(ValueAnimator animation) { float curValue = (float) animation.getAnimatedValue(); / / the current value float fraction = animation. GetAnimatedFraction (); // The proportion of the current transition completed}}); animator.setDuration(2000); // Animator.start ();Copy the code

Valueanimator.offloat () is a smooth transition for floating-point numbers. Valueanimator.ofint () is used in the same way if smooth transitions are needed for integers. OfArgb (), valueAnimator.ofObject (), valueAnimator.ofarGb (), valueAnimator.ofarGb (), valueAnimator.ofarGB (), valueAnimator.ofarGB () Valueanimator.ofobject () can be used to implement the transition effect of an object, so we need to define our own extension. How does valueanimator.offloat () achieve the transition effect? This is done with a FloatEvaluator that continuously evaluates the current value:

public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); }}Copy the code

If we want to transition from Point(0, 0) to Point(100, 100), we also need to implement a TypeEvaluator to calculate the current transition property value:

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.x + fraction * (endPoint.x - startPoint.x); float y = startPoint.y + fraction * (endPoint.y - startPoint.y); return new Point((int) x, (int) y); }}Copy the code

Very simply, the fraction represents the percentage of transitions that have been completed. The value of the current point is calculated based on the percentage of transitions that have been completed currently, the start point, and the end point. With PointEvaluator we can implement our own Point transitions:

Point startPoint = new Point(0, 0); Point endPoint = new Point(100, 100); ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Point currPoint = (Point) animation.getAnimatedValue(); }});Copy the code

This allows us to implement a custom evaluator through TypeEvaluator. ValueAnimator is a smooth animation transition for values. ObjectAnimator is a subclass of ValueAnimator that animates properties of any object. 2.1 Pan Animation To move a View right off the screen and back, you can do this:

float translationX = view.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", translationX, 600f, translationX);
animator.setDuration(3000);
animator.start();Copy the code

With the ofFloat() method we create an ObjectAnimator. The first argument to the ofFloat() method, view, is the object that we want to translate. Because we want to translate the view, the second argument is passed to translationX, Represents the pan property of the view, and then the argument is a variable length, depending on how many you want. So the core argument is the second one, which differentiates what to animate the View based on this property type. In the same way, you can scale a View like this:

ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleX", 1f, 2f, 1f);
animator.setDuration(5000);
animator.start();Copy the code

We changed the ofFloat() method’s second argument to scaleX, which represents scaling the view in the x direction, and we achieved the view stretching twice and then restoring. For example, if you want to rotate a View 360 degrees, you can do this by writing the second argument ofFloat() as the rotation, starting at 0 and ending at 360:

ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);
animator.setDuration(3000);
animator.start();Copy the code

As long as the second parameter ofFloat() is written as alpha, then the View transparency changes from 1 to 0:

ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
animator.setDuration(5000);
animator.start();Copy the code

It is also possible to use property animation to change the background color of a View. The following code can change the background color of a View from blue to red:

ObjectAnimator animator = ObjectAnimator.ofFloat(view, "backgroundColor", Color.BLUE, Color.RED);
animator.setEvaluator(new ArgbEvaluator());
animator.setDuration(5000);
animator.start();Copy the code

2.6 Composite Animation is similar to tween animation, attribute animation can also combine single animation, and its function is more powerful. It needs to be realized through the AnimatorSet class. An AnimatorSet. After (Animator anim) inserts the existing animation into the incoming animation after(long delay) inserts the existing animation into the incoming animation before(Animator anim) inserts the existing animation into the incoming animation With (Animator anim) executes the existing animation and the incoming animation at the same time. We want to create a View that moves from the right side of the screen to the right side of the screen, rotates it 360 degrees and changes the opacity. Finally, we want to restore the effect by stretching it twice horizontally.

AnimatorSet animatorSet = new AnimatorSet();

ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);
ObjectAnimator translation = ObjectAnimator.ofFloat(view, "translationX", 600f, 0f);
ObjectAnimator scale = ObjectAnimator.ofFloat(view, "scaleX", 1f, 2f, 1f);

animatorSet.play(alpha).with(rotation).after(translation).before(scale);
animatorSet.setDuration(5000);
animatorSet.start();Copy the code

You can also use setRepeatCount() and setRepeatMode() to set the number of iterations of the animation and the repeat mode. The repeat modes are valueanimator.restart and valueanimator.reverse. 3. In addition to animating properties in code, you can also use XML, which needs to be placed in the Animator folder under the RES directory. The following three labels are available:

  • On behalf of the ValueAnimator
  • On behalf of the ObjectAnimator
  • To achieve a smooth transition from 0 to 50, we can do this:

    
    Copy the code

    To rotate a View 360 degrees, do this:

    
    Copy the code

    To change the transparency of a View from 1 to 0, write:

    
    Copy the code

    Pan and zoom animations are similar. Look again at the use of tags:

    
    
      
    
      
          
    
          
              
              
          
      
    
      
          
    
          
      
    Copy the code

    We have animated the View to pan, rotate and change transparency simultaneously, and then scale. The ordering phase is sequentially and together, which means playing in sequence and at the same time. There are also two properties we didn’t use: startOffset: indicates the animation’s delayed start time, and repeatCount and repeatMode. Using an XML animation file is also very simple:

    Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);  
    animator.setTarget(view);  
    animator.start();Copy the code

    ObjectAnimator, ValueAnimator, and AnimatorSet are subclasses of Animator. ObjectAnimator, ValueAnimator, and AnimatorSet are subclasses of Animator. So they can all use addListener() :

    anim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation)  { } @Override public void onAnimationRepeat(Animator animation) { } });Copy the code

    If you want to listen for some of these events, you can use the AnimatorListenerAdapter to do so:

    animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); } @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); }});Copy the code

    So we only listen for the start and end events of the animation.

5. The interpolator of property animation is compatible with the interpolator of tween animation, so the interpolator of tween animation can be used in property animation. Attribute animation provides a TimeInterpolator interface that calculates the percentage change in the current value of a property based on the percentage time elapsed. By this interface we will interpolate the interpolator:

public interface TimeInterpolator { /** * Maps a value representing the elapsed fraction of an animation to a value that  represents * the interpolated fraction. This interpolated value is then multiplied by the change in * value of an Animation to derive the animated value at the current Elapsed animation time. * * @param input A value between 0 and 1.0 Was it where the animation where 0 showed me the start and 1.0 showed me the end * @return the Interpolation value. This value can be more than 1.0 for * interpolators which overshoot their targets, or less than 0 for * interpolators that undershoot their targets. */ float getInterpolation(float input); }Copy the code

There is only one getInterpolation() method in the interface, where the input parameter changes at a constant rate between 0 and 1 depending on the duration of the animation set. To customize the interpolator, write:

public class MyInterpolator implements TimeInterpolator { @Override public float getInterpolation(float input) { float result = 0; //todo return result; }}Copy the code

It’s time to test your math skills… See system interpolator for implementation details. One thing to note is that the value of result must be between 0 and 1.

5. 6. Smart refrigerator We can animate properties in Java code with objectAnimator.offloat () or objectAnimator.ofint () where the second argument can be alpha, rotation, scaleX, translateX, and so on. Why can the second argument be these? This is because ObjectAnimator’s internal working mechanism does not operate on the name of the property passed in. Instead, ObjectAnimator uses the name of the property to find the corresponding get and set methods in the current child View class and its parent class, and then constantly changes the values of the methods to achieve the animation effect. For example, we can find the get and set methods for the rotation argument in the View class:

public float getRotation() {
        return mRenderNode.getRotation();
    }

public void setRotation(float rotation) {
        if (rotation != getRotation()) {
            // Double-invalidation is necessary to capture view's old and new areas
            invalidateViewProperty(true, false);
            mRenderNode.setRotation(rotation);
            invalidateViewProperty(false, true);

            invalidateParentIfNeededAndWasQuickRejected();
            notifySubtreeAccessibilityStateChangedIfNeeded();
        }
    }Copy the code

In addition to the attribute animation provided by the system, if we want to add a widths animation to a custom Button and change its width, using the translateX attribute will cause the Button content to stretch, which is not desirable. So our custom widths animations don’t have this problem. Let’s start with our custom Button class:

public class MyButton extends Button{ public MyButton(Context context) { super(context); } public MyButton(Context context, AttributeSet attrs) { super(context, attrs); } public int getWidths(){ return getLayoutParams().width; } public void setWidths(int width){ getLayoutParams().width = width; requestLayout(); }}Copy the code

Since we specify the property name widths, we provide getWidths() and setWidths(), which are also required. Next we need to write a TypeEvaluator class to tell the system how the width transitions:

public class WidthsEvaluator implements TypeEvaluator {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startWidth = (int) startValue;
        int endWidth = (int) endValue;
        return (int)(startWidth + fraction * (endWidth - startWidth));
    }Copy the code

With the WidthsEvaluator class, all we need is a look at the layout file and how to use it:




    

    Copy the code
Copy the code
public class MainActivity extends AppCompatActivity { private MyButton button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (MyButton) findViewById(R.id.my_btn); } public void start(View view) { int width = button.getWidth(); ObjectAnimator animator = ObjectAnimator.ofObject(button, "widths", new WidthsEvaluator(), width, 600); animator.setDuration(3000); animator.start(); }}Copy the code

Objectanimator.ofobject (). It’s very simple.




MyButton

7. In addition to the ObjectAnimator class, there is another way to animate properties through Java code, which is to use the ViewPropertyAnimator class. For example, if we want to implement a spherical View in free fall, we can write:

view.animate().x(0).y(500)
    .setDuration(5000)  
    .setInterpolator(new BounceInterpolator());Copy the code

The animation is performed automatically after the animation is generated using the view.animate() method. All subsequent actions are chained to the ViewPropertyAnimator, and start() is added at the end of the animation. Just different writing methods, choose according to preference, other methods are interested if you can test yourself.

Three, frame animation

Frame animation is to play a series of pictures in sequence, so as to produce the effect of animation, in fact, is the switch of pictures. However, if the image is too many, too large is easy to produce OOM, so use caution. Start by writing an XML file in the Drawable folder under the RES directory:


//
    
    
    
    
    
    
    
    
    
Copy the code

The oneshot property indicates whether the loop is played, or true, only once.

Call with the following method, where the view is an ImageView object:

view.setImageResource(R.drawable.icons);
AnimationDrawable animationDrawable = (AnimationDrawable) view.getDrawable();
animationDrawable.start();Copy the code

To stop the playback, you can use the following methods:

AnimationDrawable animationDrawable = (AnimationDrawable) view.getDrawable();
animationDrawable.stop();Copy the code

This is the end of Android animation-related content for use scenarios in development.