Android animation (3) interpolator, estimator, how to use object

Interpolator, estimator, how to use object

First, let me talk about my understanding of the interpolator and estimator.

  • The interpolator is used to calculate the rate of change of the animation execution.
  • The estimator is to calculate the rate of the interpolator and the start value and end value we set, and calculate the attribute values ​​required for each frame of animation.

Interpolator

It can be found through the source code that all the interpolators under android implement a TimeInterpolator interface:

/**
 * A time interpolator defines the rate of change of an animation. This allows animations
 * to have non-linear motion, such as acceleration and deceleration.
 */
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 indicating our current point
     *        in the animation where 0 represents the start and 1.0 represents
     *        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);
}

Incoming input is where the animation is executed, and it is a float type between 0 and 1.
The return value is the calculated float value. The value can be less than 0 or greater than 0.
For example, if I pass in 0.5 to indicate half of the animation execution, if it is the calculation method in AccelerateInterpolator, it will return 0.5 * 0.5 = 0.25 to us, of course, we can pass a float to change the input value during initialization Perform multiple power operations:

public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    private final float mFactor;
    private final double mDoubleFactor;

    public AccelerateInterpolator() {
        mFactor = 1.0f;
        mDoubleFactor = 2.0;
    }

    /**
     * Constructor
     *
     * @param factor Degree to which the animation should be eased. Seting
     *        factor to 1.0f produces a y=x^2 parabola. Increasing factor above
     *        1.0f  exaggerates the ease-in effect (i.e., it starts even
     *        slower and ends evens faster)
     */
    public AccelerateInterpolator(float factor) {//指定几次幂
        mFactor = factor;
        mDoubleFactor = 2 * mFactor;
    }

    public AccelerateInterpolator(Context context, AttributeSet attrs) {
        this(context.getResources(), context.getTheme(), attrs);
    }

    /** @hide */
    public AccelerateInterpolator(Resources res, Theme theme, AttributeSet attrs) {
        TypedArray a;
        if (theme != null) {
            a = theme.obtainStyledAttributes(attrs, R.styleable.AccelerateInterpolator, 0, 0);
        } else {
            a = res.obtainAttributes(attrs, R.styleable.AccelerateInterpolator);
        }

        mFactor = a.getFloat(R.styleable.AccelerateInterpolator_factor, 1.0f);
        mDoubleFactor = 2 * mFactor;
        setChangingConfiguration(a.getChangingConfigurations());
        a.recycle();
    }

    public float getInterpolation(float input) {
        if (mFactor == 1.0f) {
            return input * input;
        } else {
            return (float)Math.pow(input, mDoubleFactor);
        }
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createAccelerateInterpolator(mFactor);
    }
}

In getInterpolation (), we can calculate various return values ​​according to various mathematical formulas to achieve beautiful animations

Estimator

package android.animation;

/**
 * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators
 * allow developers to create animations on arbitrary property types, by allowing them to supply
 * custom evaluators for types that are not automatically understood and used by the animation
 * system.
 *
 * @see ValueAnimator#setEvaluator(TypeEvaluator)
 */
public interface TypeEvaluator<T> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public T evaluate(float fraction, T startValue, T endValue);

}

We previously talked about the interpolator calculating the rate of change, but this rate of change can't be used to set the control.
The estimator converts the rate of change into a value. The fraction passed into this evaluate () is the value we calculated from the interpolator and the animation execution percentage. This value can be greater than 0 or less than 0. startValue and endValue are Let's take a look at the value passed in from the function ofInt (), take a look at IntEvaluator:

/**
 * This evaluator can be used to perform type interpolation between <code>int</code> values.
 */
public class IntEvaluator implements TypeEvaluator<Integer> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value; should be of type <code>int</code> or
     *                   <code>Integer</code>
     * @param endValue   The end value; should be of type <code>int</code> or <code>Integer</code>
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
}

In fact, these three values ​​are used to calculate the attribute value of the animation execution to the frame of fration.

ofObject()

After understanding the role of the interpolator and estimator, it is very simple to use ofObject ()
. As the name implies, the attribute value is set to the object type, but what type of object () is it? The Android system does not know , So we need to set up our own estimator to return the type we want, see an example: refer to other people ’s

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
    fun click(view: View) {
        val tv = findViewById<MyTextView>(R.id.tv)
        val holder = PropertyValuesHolder.ofObject(
            "IntText",
            IntEvaluator(),
            1,
            30
        )
        val animator = ObjectAnimator.ofPropertyValuesHolder(tv, holder)
        animator.duration = 3000
        animator.interpolator = LinearInterpolator()
        animator.start()
    }
}
class IntEvaluator : TypeEvaluator<Int>{
    override fun evaluate(fraction: Float, startValue: Int?, endValue: Int?): Int {
        val curInt = startValue!! + fraction * (endValue!! - startValue!!)
        return curInt.toInt()
    }
}

TextView does not set text to Int function, so we inherited TextView and wrote a

class MyTextView(context: Context?, attrs: AttributeSet?) :
    TextView(context, attrs) {
    fun setIntText(int : Int) {
        text = int.toString()
    }
}

Insert picture description here
Here we have a simple estimator that returns an Int type

We pass in a propertyName = "IntText" in ofObject, which corresponds to which setIntText () method we wrote, remember it first.
Ok, these sections talk about API calls, but we do n’t know the working principle. The next section is how it works.

Published 16 original articles · liked 0 · visits 249

Guess you like

Origin blog.csdn.net/weixin_43860530/article/details/105352554