Android animation collection attribute animation-see again


Introduction to this section:

In the previous section, we conducted a preliminary study of Android’s property animation. I believe that everyone is no longer interested in property animation. Now that we have a little knowledge of it, in this section we will continue to explore some more advanced uses of Android property animations! Still posting three articles by Guo Shen~

Complete analysis of Android attribute animation (Part 1), first understanding of the basic usage of attribute animation

Android attribute animation Complete analysis (Part 2), advanced usage of ValueAnimator and ObjectAnimator

Complete analysis of Android property animation (Part 2), usage of Interpolator and ViewPropertyAnimator

The content is still Refer to the above three articles, okay, let’s start this section~


1. Evaluator customization

1) Evaluator introduction

In the previous section8.4.3 Attribute Animation of Android Animation Collection-First See, the first step in using animation is:

Call ValueAnimatorofInt (), ofFloat() or ofObject() static method creates a ValueAnimator instance!

In the example, we have used both ofInt and ofFloat, which are used to animate floating-point and integer data respectively!

So ofObject()? Initial object and end object? How to transition? Or how to use this thing?

Okay, with questions, let’s first understand one thing: Evaluator. In fact, we talked about this thing when we talked about the concept of attribute animation:

1.png

is used to tell the animation system how to transition from the initial value to the end value! Okay, our starting point is right! Let's go into the source code of IntEvaluator and see what's written in it?

2.png

Well, I implemented the TypeEvaluator interface, and then rewrote the evaluate() method. There are three parameters, in order:

  • fraction: The degree of completion of the animation, we calculate the value of the animation based on it
  • startValue: The start of the animation Initial value
  • endValue: The end value of animation

The value of animation = initial value + degree of completion* (end value-initial value)

The same is true for FloatEvaluator. We want to tell the system how to transition from the initial object to the end object, then we have to Implement the TypeEvaluator interface by yourself, that is, customize the Evaluator. It is useless to talk about it. Write an example to see:

2) Usage example

Operation renderings:

3.gif

Code implementation:

Define an objectPoint.java. There are only two attributes x and y in the object and get, set method~

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class Point {

    private float x;
    private float y;

    public Point() {
    }

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }

    public void setX(float x) {
        this.x = x;
    }

    public void setY(float y) {
        this.y = y;
    }
}

Then customize the Evaluator class: PointEvaluator.java, implement the interface and rewrite the evaluate method~

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class PointEvaluator implements TypeEvaluator{
    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        float x = startValue.getX() + fraction * (endValue.getX() - startValue.getX());
        float y = startValue.getY() + fraction * (endValue.getY() - startValue.getY());
        Point point = new Point(x, y);
        return point;
    }
}

Then customize a View class:AnimView.java, very simple~

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class AnimView extends View {

    public static final float RADIUS = 80.0f;
    private Point currentPoint;
    private Paint mPaint;

    public AnimView(Context context) {
        this(context, null);
    }

    public AnimView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public AnimView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }

    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 onAnimationUpdate(ValueAnimator animation) {
                currentPoint = (Point) animation.getAnimatedValue();
                invalidate();
            }
        });
        anim.setDuration(3000l);
        anim.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            drawCircle(canvas);
            startAnimation();
        } else {
            drawCircle(canvas);
        }
    }
}

Finally, instantiate this View at MainActivity.java~

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new AnimView(this));
    }
}

3) Example Enhanced version

Based on our above example, we add the color change when the circle moves~ Here we use another ObjectAnimator to load the color change animation. We add multiple int color to control the color, and write the getColor() and setColor() methods. Let’s customize an Evaluator first~

Running renderings:

4.gif

Implementation code

ColorEvaluator.java

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class ColorEvaluator implements TypeEvaluator{
    @Override
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int alpha = (int) (Color.alpha(startValue) + fraction *
                (Color.alpha(endValue) - Color.alpha(startValue)));
        int red = (int) (Color.red(startValue) + fraction *
                (Color.red(endValue) - Color.red(startValue)));
        int green = (int) (Color.green(startValue) + fraction *
                (Color.green(endValue) - Color.green(startValue)));
        int blue = (int) (Color.blue(startValue) + fraction *
                (Color.blue(endValue) - Color.blue(startValue)));
        return Color.argb(alpha, red, green, blue);
    }
}

Then add a color to the custom View, get and set method; create an ObjectAnimator, and AnimatorSet, and then combine the animations together. I will just add a few things here, in case readers have any questions. Just create another View~

AnimView2.java

/**
 * Created by Jay on 2015/11/18 0018.
 */
public class AnimView2 extends View {

    public static final float RADIUS = 80.0f;
    private Point currentPoint;
    private Paint mPaint;
    private int mColor;

    public AnimView2(Context context) {
        this(context, null);
    }

    public AnimView2(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public AnimView2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }



    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 onAnimationUpdate(ValueAnimator animation) {
                currentPoint = (Point) animation.getAnimatedValue();
                invalidate();
            }
        });

        ObjectAnimator objectAnimator = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(),
                Color.BLUE, Color.RED);
        //动画集合将前面两个动画加到一起,with同时播放
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(anim).with(objectAnimator);
        animatorSet.setStartDelay(1000l);
        animatorSet.setDuration(3000l);
        animatorSet.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            drawCircle(canvas);
            startAnimation();
        } else {
            drawCircle(canvas);
        }
    }

    //color的get和set方法~
    public int getColor() {
        return mColor;
    }

    public void setColor(int color) {
        mColor = color;
        mPaint.setColor(color);
        invalidate();
    }
}

Then MainActivity, setContentView and change AnimView to AnimView2~


2.Interpolator(Tweener)

Well, we have already talked about this stuff when we talked about tweening animation~ I wonder if you still remember it?

The above tweener tweening animation and attribute animation are available, and the tweening animation also adds a new TimeInterpolator interface This interface is used to be compatible with previous Interpolator, which allows all past Interpolator implementation classes to be directly used Use it in attribute animation! We can call the setInterpolator() method of the animation object to set different Interpolators! We need to click something first and let the ball fall from the top to the bottom in the center of the screen~ Then we will call the following statement for our set animation: animatorSet.setInterpolator(new AccelerateInterpolator(2f));The values ​​in brackets are used to control acceleration~

Run Effect :

5.gif

seems a bit unconventional. Normally it should bounce. Let’s try it with BounceInterpolator~

6.gif

Hehe, the effect is quite good. Of course, there are many good Interpolators provided by N systems. You can try them one by one. Here are I don’t want to get entangled with you slowly~

Let’s take a look:

1) The internal implementation mechanism of Interpolator

We first go to the source code of the TimeInterpolator interface and find that there is only one getInterpolation() method;

7.png

Simple explanation: The getInterpolation() method receives an input parameter. The value of this parameter will continue to change as the animation runs. However, its changes are very regular, that is, it increases at a constant speed according to the set animation duration, and the change range is 0 to 1. That is to say, when the animation begins, the value of input is 0, when the animation ends, the value of input is 1, and the value in the middle is It changes between 0 and 1 as the animation runs.

The input value here determines the value of fraction in our TypeEvaluator interface. The input value is calculated by the system and passed into the getInterpolation() method. Then we can implement the algorithm in the getInterpolation() method ourselves and calculate a return value based on the input value, and This return value is the fraction.

We can look at the code in LinearInterpolator:

8.png

There is no processing here to directly return the input value, that is, the value of fraction is Equal to the value of input, this is uniform motion How Interpolator is implemented! In fact, it is nothing more than different algorithms, which involves some mathematical things. Once again Now that I have realized the importance of mathematics, here is the source code of BounceInterpolator:

9.png

Don’t ask me about the algorithm here, I don’t know either. , let’s find something easier to understand: AccelerateDecelerateInterpolator

This Interpolator accelerates first and then decelerates: (float)(Math.cos( (input + 1) * Math.PI) / 2.0f) + 0.5f Algorithm understanding: 10.png

Solution: From input The value range is [0,1]. It can be concluded that the value range of cos is [π,2π], and the corresponding values ​​are -1 and 1; After dividing this value by 2 and adding 0.5, the final result value returned by the getInterpolation() method is still in the range [0,1]. The corresponding curve chart is as follows:

So it is a process of accelerating first and then decelerating!

Well, I’m a scumbag and can’t play anymore...11.gif, all the above are copied from Uncle Guo’s article...I want to be quiet...

2) Custom Interpolator

Okay, let’s worry about it later. Let’s write a custom Interpolator example first: Very simple, implement the TimeInterpolator interface and rewrite the getInterpolation method

The sample code is as follows

private class DecelerateAccelerateInterpolator implements TimeInterpolator {
    @Override
    public float getInterpolation(float input) {
        if (input < 0.5) {
            return (float) (Math.sin(input * Math.PI) / 2);
        } else {
            return 1 - (float) (Math.sin(input * Math.PI) / 2);
        }
    }
}

Call setInterpolator(new DecelerateAccelerateInterpolator()) to set it~ Due to space limitations, no pictures will be posted~


3. ViewPropertyAnimator

A new function added to the system after 3.1 provides a more convenient usage for View animation operations! If it were before, to change a TextView from normal state to transparent state, it would be written like this:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 0f);  
animator.start();

And using ViewPropertyAnimator to achieve the same effect is more understandable:

textview.animate().alpha(0f);

also supports Concatenation usage, combine multiple animations, set duration, set Interpolator, etc.~

textview.animate().x(500).y(500).setDuration(5000)  
        .setInterpolator(new BounceInterpolator());

The usage is very simple, just check the documentation when using it~, and there are a few details below Pay attention!

  • The entire ViewPropertyAnimator function is based on the new animate() method of the View class. This method will create and return an instance of ViewPropertyAnimator, and all subsequent methods will be called. All properties set are done through this instance.
  • After using ViewPropertyAnimator to define the animation, the animation will start automatically. And this mechanism is also effective for combined animations, as long as we continue to add new methods, Then the animation will not be executed immediately. After all the methods set on ViewPropertyAnimator are executed, The animation will start automatically. Of course, if we don't want to use this default mechanism, we can also explicitly call the start() method to start the animation.
  • All interfaces of ViewPropertyAnimator are designed using concatenated syntax, and the return value of each method is Itis an instance of itself, so after calling one method, you can directly call another of its methods in succession, so that all The functions are all connected in series, and we can even complete animation functions of any complexity with just one line of code.

4. Download the sample code for this section

AnimatorDemo3.zip

Find an animation collection project on Github, with many animation effects. Paste the address below:

BaseAnimation animation collection

If you want to study how various animations are implemented, you can view the source code yourself~


Summary of this section

Well, in this section we talked about some slightly more advanced things like Evaluator, Interpolator, and ViewPropertyAnimator, has it expanded everyone’s knowledge~ This section is also the basic introductory drawing of Android This is the last section of the chapter. If you have mastered the contents of this chapter, then go to learn custom controls. Or if you look at the custom controls written by others, you should no longer be so confused about where to start and meet a bunch of new faces!

Well, thank you to Guo Shen for your article. The content of the attribute animation part was directly transferred from Guo Shen. 12.jpg Hehe~ That’s it for this section, thank you~

PS: Later The schematic diagram changed the simulator because the N5 show was funny...