1. Introduction

Before the introduction of property animation, Android already had a Tween Animation. The new Animator was introduced because of the limitations of tween animations. Classification of tween animation:

  1. AlphaAnimation
  2. ScaleAnimation
  3. TranslateAnimation
  4. RotateAnimation
  5. AnimationSet

Limitations of tween animation:

  1. The number of objects you can animate is limited
  2. The display area and clickable area may differ

ValueAnimator and ObjectAnimator are introduced on Android3 to complement and address the above shortcomings of tween animation.

2. Property animation

2.1 Formation structure of attribute animation

The serial number The name of the class instructions
1 Animator The parent class of all Animators, used primarily to define generic interfaces
2 AnimatorSet Multiple property animation combinations
3 ValueAnimator Mainly used to generate animation based on starting and ending values, only responsible for generating values between starting and ending values
4 ObjectAnimator It is mainly used to generate an animation based on the start and end values and to set the resulting values on the target object
5 TimeAnimator Provides a simple callback mechanism, through TimeAnimator. TimeListener, notify you at each frame of animation. (Not covered in this article)

Inheritance structure:

2.2 Define property animation methods

As with tween animations, you can create animations using Xml and Code.

Create an XML animation file in the Animation folder. (If there is no animation folder, create it manually.)

<objectAnimator
   android:duration="int"
   android:interpolator="@[package:]anim/interpolator_resource"
   android:propertyName="string"
   android:valueType=["intType"|"floatType"]
   android:valueFrom="float | int | color"
   android:valueTo="float | int | color"
   android:startOffset="int"
   android:repeatCount="int"
   android:repeatMode=["repeat"|"reverse"/ >
Copy the code
attribute meaning Value range
duration Animation execution time Integer, needs to be greater than 0.
interpolator A differentiator that changes the rate at which the animation or value changes Android comes with it, custom
propertyName Animate the property of the target object to change String, fill in the property name
valueType Value types Point type, floating point type. Can be omitted when the type of the property animation value is color value
valueFrom The starting value of the animation value Floating-point, integer, or color values. When is a color value, it must conform to the way the color is defined (# + six hexadecimal numbers)
valueTo The end value of the animation value Floating-point, integer, or color values. When is a color value, it must conform to the way the color is defined (# + six hexadecimal numbers)
startOffset The animation starts to offset time An integer. The default value is 0. When negative, the effect is the same as the default value
repeatCount The number of times the animation repeats An integer number. The default value is 0. When it is negative, it indicates an infinite loop
repeatMode How the next animation executes Default: Restart playback. And pour on
The sample
//1. Create an XML file in the animation folder<? xml version="1.0" encoding="utf-8"? > <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:propertyName="rotation"
    android:valueType="floatType"
    android:valueFrom="0"
    android:valueTo="360"
    android:startOffset="0"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    />
    
//2. Import the animation XML in your code
val objectAnimator = AnimatorInflater.loadAnimator(this, R.animator.object_animator) as ObjectAnimator
objectAnimator.setTarget(target)
objectAnimator.start()

Copy the code

How the code is created is described below.

3. ValueAnimator

ValueAnimator is, as its name suggests, a computational animation of numbers. Instead of interacting directly with the View, ValueAnimator#addUpdateListener sets the animation effect. For example, a ValueAnimator can be used to display values from 0 to 50 on a TextView.

3.1 Creating ValueAnimator

Create ValueAnimator in your code.

// Create the Animator, passing in a range of values
val animator = ValueAnimator.ofFloat(0F, 5000F) 
// Set the differentiator, where the linear differentiator is selected
animator.interpolator = LinearInterpolator()
// Set the animation execution time
animator.setDuration(2000)
Copy the code

If you don’t set the interpolator, the default is used AccelerateDecelerateInterpolator (). If set to NULL, the LinearInterpolator() is used by default.

3.2 add UpdateListener

The onAnimationUpdate interface is called when there is a value change in ValueAnimator. So we need to implement this Listener.

animator.addUpdateListener {
    // Update text in TextView
    binding.textView.text = ((it.animatedValue as Float).toInt() / 100).toString()
    // The value is passed into the custom Bessel View to animate it
    binding.bezierView.setValue(it.animatedValue as Float)}Copy the code

Custom Bessel View source as follows. For Bessel curves, see another article of mine.

class BezierView : View {

    private var path: Path = Path()

    private lateinit var paint: Paint = Paint()

    private var h: Int = 0
    private var w: Int = 0

    private var controlPoint1: PointF = PointF()
    private var controlPoint2: PointF = PointF()

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attributeSet: AttributeSet?) : super(context, attributeSet)

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)

        // Set the height and width of the current view
        this.h = h
        this.w = w

        controlPoint1 = PointF(this.w.toFloat() / 4.0F)
        controlPoint2 = PointF(this.w.toFloat() / 4 * 3.this.h.toFloat())
    }

    fun setValue(degree: Float) {
        val controlY = degree / 5000 * h

        controlPoint1 = PointF(this.w.toFloat() / 4, controlY)
        controlPoint2 = PointF(this.w.toFloat() / 4 * 3.this.h.toFloat() - controlY)

        invalidate()
    }
    
    override fun onDraw(canvas: Canvas?). {
        super.onDraw(canvas)

        // Reset path to prevent repeated Bezier curves from leaving multiple curves on the canvas
        path.reset()

        // Configure the brush paint
        paint.color = context.getColor(R.color.colorAccent)
        paint.strokeWidth = 2F
        paint.style = Paint.Style.STROKE

        // Set the left and right reference points
        val pointLeft = PointF(0F, h / 2.toFloat())
        val pointRight = PointF(w.toFloat(), h / 2.toFloat())

        // Draw the left and right reference pointscanvas? .drawPoint(pointLeft.x, pointLeft.y, paint) canvas? .drawPoint(pointRight.x, pointRight.y, paint) paint.color = context.getColor(R.color.colorPrimaryDark)// To draw the Bezier curve, move to one of the reference points
        path.moveTo(pointLeft.x, pointLeft.y)

        // Draw bezier curves according to datum and control points
        path.cubicTo(
            controlPoint1.x,
            controlPoint1.y,
            controlPoint2.x,
            controlPoint2.y,
            pointRight.x,
            pointRight.y
        )

        // Draw path on the canvascanvas? .drawPath(path, paint) } }Copy the code

3.3 Playing Animations

Finally, you need to start playing the animation at the appropriate node.

// Play the animation
animator.start()
// Animation is tentative
animator.pause()
// End of playback
animator.end()
Copy the code

4. ObjectAnimator

ObjectAnimator is created in the same way as ValueAnimator.

// Create animation,
val objectAnimator = ObjectAnimator.ofFloat(binding.imageView, "rotation".0F, 360F, 0F)
// Set the animation execution time
objectAnimator.setDuration(2000)
// Start playing
objectAnimator.start()
Copy the code

The first argument to create an animation is the View object being animated, the second is properyName, and the third is the starting value of the variable length argument.

There are the following types of propertyName:

The name of the role
alpha transparent
rotation rotating
rotationX It’s rotating around the X-axis
rotationY It’s rotating on the Y axis
translationX It’s shifted in the X-axis
translationY It’s shifted in the Y axis
scaleX It’s stretched in the X-axis
scaleY It’s stretched in the Y-axis

5. Property animation Listener

There are three types of listeners for property animations.

  1. AnimatorListener
  2. AnimatorPauseListener
  3. AnimatorUpdateListener

5.1 AnimatorListener

The AnimatorListener listener listens for the start, end, cancel, and repeat of the property animation.

public static interface AnimatorListener{
    void onAnimationStart(Animator animation, boolean isReverse) {}
    
    void onAnimationEnd(Animator animation, boolean isReverse) {}
    
    void onAnimationCancel(Animator animation, boolean isReverse) {}
    
    void onAnimationRepeat(Animator animation, boolean isReverse) {}}Copy the code

5.2 AnimatorPauseListener

The AnimatorPauseListener listener listens for the paused and resumed state of the property animation.

public static interface AnimatorPauseListener {
    void onAnimationPause(Animator animation);
    
    void onAnimationResume(Animator animation);
}
Copy the code

5.3 AnimatorUpdateListener

The AnimatorUpdateListener listener listens primarily for changes in the value of the property animation.

public static interface AnimatorUpdateListener {
    void onAnimationUpdate(ValueAnimator animation);
}
Copy the code

Interpolator 6. Interpolator

6.1 Interpolator types

Interpolator for attribute animation is the same as Interpolator for tween animation. There are several types of interpolators:

The name of the role
AccelerateDecelerateInterpolator Speed up first, then slow down
AccelerateInterpolator Has been accelerated
AnticipateInterpolator Detour, speed up
OvershootInterpolator Accelerate over and return to the end
AnticipateOvershootInterpolator Detour, accelerate beyond, return to the end
BounceInterpolator Spring effect
CycleInterpolator Sine curve
DecelerateInterpolator Has been slow
LinearInterpolator Linear speed

6.2 Custom interpolators

If the above interpolator does not meet the requirements, you can define a new interpolator. BaseInterpolator inherits when you define an interpolator. Rewrite public float getInterpolation(float Input).

The linear interpolator is the following code and can be used as a reference.

public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator(a) {}public LinearInterpolator(Context context, AttributeSet attrs) {}public float getInterpolation(float input) {
        return input;
    }

    / * *@hide* /
    @Override
    public long createNativeInterpolator(a) {
        returnNativeInterpolatorFactoryHelper.createLinearInterpolator(); }}Copy the code

7. Custom TypeEvaluator

The estimator is used to calculate numerical changes in ValueAnimator. The default ValueAnimator is linear. Public T evaluate(float Fraction, T startValue, T endValue); .

The following is an example:

class CustomTypeEvaluator : TypeEvaluator<Float> {
    override fun evaluate(fraction: Float, startValue: Float? , endValue:Float?).: Float {
        returnfraction * abs(endValue ? :0F - startValue!!) }}Copy the code

8. Github

Examples of this article: github.com/HyejeanMOON…

Other tutorials: Using Google’s MergeAdapter: juejin.cn/post/684490… Paging in Android: juejin.cn/post/684490… Android UI testing Espresso: juejin.cn/post/684490… Android ConstraintLayout: juejin.cn/post/684490… In RecyclerView can cope with multiple ViewType libraries -Groupie: juejin.cn/post/684490…