1. A brief introduction

Android has three kinds of animation, which are view animation, property animation and frame animation.

Among them, the frame animation has been abandoned because of insufficient resources, poor performance, memory overflow and so on.

Attribute animation is the most commonly used animation scheme on Android, with the following advantages:

  1. Animation effects include but are not limited to translation, rotation, scaling, transparency;
  2. Objects include but are not limited to View;
  3. Under the same conditions, property animation performance & resource consumption is better than view animation.
  4. Highly customizable

Principle 2.

The ValueAnimator class animates objects in real time by controlling changes in values

The ObjectAnimator class animates the object directly by changing its property values

3. Use ValueAnimator

ValueAnimator has three animator constructor methods :(int values), ofFloat (float values), ofObject (int values)

The difference between the three methods can be understood as the use of different estimators, the principle is the process of value change.

Property animation is recommended to obtain animation objects in Java dynamic code, which is convenient and flexible to set values.

3.1 ofFloat

Use floating-point evaluator, FloatEvaluator, to change the initial value to the end value as a float

public static Animator startValueAnim(float. changeArr ,){
// ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); // Smooth transition from 0 to 1
        ValueAnimator anim = ValueAnimator.ofFloat(changeArr);// passing several is a continuous transition to each value until the last value, such as 0,1,0.8, 1
        anim.setDuration(300);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {}});return anim;
    }
Copy the code

3.2 ofInt

In the same way ofFloat is used, ofInt uses an integer valuator to change an initial value from an int value to an end value


    public static Animator startValueAnim(int. changeArr ,){
// ValueAnimator anim = ValueAnimator.ofFloat(0, 100); // Smooth transition from 0 to 100
        ValueAnimator anim = ValueAnimator.ofInt(changeArr);// passing several is a continuous transition to each value until the last value, such as 0,100,20,100
        anim.setDuration(300);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {}});return anim;
    }
Copy the code

3.3 ofObject

TypeEvaluator class ofObject is a core member of ValueAnimator. The ofObject class implements TypeEvaluator.

public class FloatOutEvaluator implements TypeEvaluator {
    / * * * *@paramFraction Indicates the progress value *@paramStartValue startValue *@paramEndValue endValue *@return* /
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        float cf = fraction;
        if (fraction<0.3 f){
            cf = fraction*2;// Top 30% progress - Double progress
        }else if (fraction <0.6 f){
            cf = 0.6 f;// Pause for a moment
        }
        returnstartFloat + cf* (((Number) endValue).floatValue() - startFloat); }}Copy the code

use

        ValueAnimator animator = ValueAnimator.ofObject(new FloatOutEvaluator() , 0f.1f);
        animator.setDuration(3000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                // Use change values, assign values, refresh, animateview.setAlpha((Float) valueAnimator.getAnimatedValue()); }});Copy the code

4. ObjectAnimator

ObjectAnimator is one of the most used animations in Android development. You can create several animations and combinations of animations directly

4.1 Java code mode

Animation: Transparent gradient twice

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

In the same way:

  1. Rotate the rotation
  2. TranslationX, translationY
  3. Scale scaleX, scaleY
  4. Transparent change alpha

XML 4.2 way

The directory of the property animation XML resource file is res/animator, not the same as the resource directory res/anim for view animation

For example,

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="0"
    android:valueTo="1.0"
    android:valueType="floatType"
    android:propertyName="alpha"/>
Copy the code

Loading use animation

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

Same with other animations rotateion, scale, translate..

4.3 ObjectAnimator extension & Custom TypeEvaluator

Expand the “color” animation

1. Define a View that contains the setColor() method

class ColorTextView extends TextView {

    public void setColor(String color){
        setTextColor(Color.parseColor(color));
    }

    public ColorTextView(Context context) {
        super(context);
    }

    public ColorTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs); }}Copy the code

2. Layout use


      
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <com.cupster.animation.ColorTextView
        android:id="@+id/anim_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Test color animation text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code

3. Write ColorEvaluator to control the rule that the color changes with the progress value

package com.cupster.animation;

import android.animation.TypeEvaluator;

Evaluator: public void setColor; invalidate() */ Evaluator: public void setColor
public class ColorEvaluator implements TypeEvaluator {

    private int mCurrentRed = -1;

    private int mCurrentGreen = -1;

    private int mCurrentBlue = -1;

    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        String startColor = (String) startValue;
        String endColor = (String) endValue;
        int startRed = Integer.parseInt(startColor.substring(1.3), 16);
        int startGreen = Integer.parseInt(startColor.substring(3.5), 16);
        int startBlue = Integer.parseInt(startColor.substring(5.7), 16);
        int endRed = Integer.parseInt(endColor.substring(1.3), 16);
        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;
        }
        // Calculate the difference between the start and end colors
        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, fraction); }// Return the calculated values of the current color
        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 = endColor; }}else {
            currentColor = (int) (startColor + (fraction * colorDiff - offset));
            if(currentColor > endColor) { currentColor = endColor; }}return currentColor;
    }

    /** * converts a decimal color value to a hexadecimal value. * /
    private String getHexString(int value) {
        String hexString = Integer.toHexString(value);
        if (hexString.length() == 1) {
            hexString = "0" + hexString;
        }
        returnhexString; }}Copy the code

4. Encapsulate common methods

public static void propColorAnimator(ColorTextView target , String startColor , String endColor){
        ObjectAnimator animator = ObjectAnimator.ofObject(target ,"color".new ColorEvaluator() ,startColor,endColor);
        animator.setDuration(3000);
        animator.start();
    }
Copy the code

5. Use


        tv = findViewById(R.id.anim_view);
        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                PropAnimatorHelper.propColorAnimator((ColorTextView) view,"#a7dbf7" ,"#ff8696"); }});Copy the code