Android View animation framework

Animation framework defines several common animations such as transparency, rotation, scaling and displacement, and controls the entire View. The realization principle is that drawChild function in the ViewGroup of the View gets the Transformation value of the Animation of the View every time the View is drawn. Then call canvas. Concat (transformToApply getMatrix ()), complete animation frames by matrix operations. If not, call invalidate() to start the next drawing to drive the animation, thus completing the entire animation. View animation is simple to use and has rich effects. It provides AlphaAnimation, RotateAnimation, TranslateAnimation and ScaleAnimation in four animation modes, as well as AnimationSet, which mixes various animations. Before Android3.0, view animation was dominant, but with the introduction of property animation frameworks after Android3.0, it’s not what it used to be. Compared with attribute animation, a very big defect of view animation is that it does not have interactivity. When an element is animated in view, the position of its response event is still in the place before the animation, so view animation can only do ordinary animation effects to avoid the occurrence of interaction. But its advantages are also very obvious, that is, high efficiency and easy to use.

View animation is very simple to use. Not only can you describe an animation process through an XML file, but you can also control the entire animation process using code.

(1) Transparency animation

Transform animation that adds transparency to the view.

AlphaAnimation aa = new AlphaAnimation(0, 1);
aa.setDuration(1000);
view.startAnimation(aa);Copy the code

(2) Rotation animation

Adds a rotating transform animation to the view.

RotateAnimation ra = new RotateAnimation(0, 360, 100, 100);
ra.setDuration(1000);
view.startAnimation(ra);Copy the code

The parameters are the starting Angle of rotation and the coordinates of the center point of rotation respectively. Of course, the reference system of the rotation animation can be controlled by setting parameters. Here, the reference system of the rotation animation is set as the center.

RotateAnimation ra1 = new RotateAnimation(0, 360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation. RELATIVE_TO_SELF, 0.5 F);Copy the code

(3) Displacement animation

Add displacement animation for view movement.

TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300);
ta.setDuration(1000);
view.startAnimation(ta);Copy the code

(4) Zoom animation

Animates the zoom of the view

ScaleAnimation sa = new ScaleAnimation(0, 2, 0, 2);
sa.setDuration(1000);
view.startAnimation(sa);Copy the code

Like rotation animation, zooming animation can also set the center of Luo Fang, set the center to its own center effect

ScaleAnimation sa1 = new ScaleAnimation(0, 1, 0, 1, animation.relative_to_self, 0.5f, animation.relative_to_self, 0.5f);  sa1.setDuration(1000); view.startAnimation(sa1);Copy the code

(5) Animation collection

AnimationSet allows animation to be represented as a composite:

AnimationSet as = new AnimationSet(true);
as.setDuration(1000);

AlphaAnimation aa = new AlphaAnimation(0, 1);
aa.setDuration(1000);
as.addAnimation(aa);


RotateAnimation ra = new RotateAnimation(0, 360, 100, 100);
ra.setDuration(1000);
as.addAnimation(ra);



TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300);
ta.setDuration(1000);
as.addAnimation(ta);

ScaleAnimation sa = new ScaleAnimation(0, 2, 0, 2);
sa.setDuration(1000);
as.addAnimation(sa);

view.startAnimation(as);Copy the code

Can directly copy the running code to see the effect!

Android also provides a listener callback for animation events:

as.setAnimationListener(new Animation.AnimationListener() {@override public void onAnimationStart(Animation Animation) {@override public void onAnimationStart Public void onAnimationRepeat(Animation Animation) {Override public void onAnimationRepeat(Animation Animation) { });Copy the code

Second, property animation

The existing Animation framework before Android3.0 has some limitations — the Animation only changes the display and does not respond to events. Therefore, after Android3.0, Google proposed a new animation framework such as attribute animation to achieve richer effects.

ObjectAnimator is used in the Animator framework in combination with AnimatorSet and ObjectAnimator. ObjectAnimator is used for more refined control, controlling only one attribute value of an object. Instead, multiple ObjectAnimators are combined into an AnimatorSet to form an animation. ObjectAnimator can be automatically driven by calling setFrameDelay(Long frameDelay) to set the interval between frames. The most important thing is that attribute animation calls attribute get and set methods to truly control the attribute value of a View, so a powerful attribute animation framework can basically achieve all animation effects.

(1) ObjectAnimator

ObjectAnimator is the most important implementation class in the attribute animation framework. Creating an ObjectAnimator simply returns an ObjectAnimator object directly through its static factory class. Arguments include an object and the name of the object’s property, but the property must also have get and set functions, which are called internally to modify the value of the object’s property through Java reflection. Similarly, you can call setInterpolator to set the corresponding discriminator.

Next, imagine adding a pan animation to a Button. Using the old animation frame, the pan animation will not trigger the click event, the effective area of the click is still the original place, and no click event will occur after clicking the move. Property animation, on the other hand, actually changes the properties of a View, so the event response area also changes, and clicking on the moved button responds to the click event.

Property animation translation code is as follows:

ObjectAnimator animator = ObjectAnimator.ofFloat(
        imageView,
        "translationX",
        200F);
animator.setDuration(300);
animator.start();Copy the code

When using ObjectAnimator, it is important that the properties to be manipulated must have get and set methods, otherwise ObjectAnimator will not work. Here are some common attributes:

  • TranslationX and translationY: These two properties, as increments, control the position of the View object from the upper-left coordinates of its layout container.
  • Rotation, rotationX, and rotationY: These three properties control 2D and 3D rotation of the View object around the fulcrum.
  • ScaleX and scaleY: These two properties control 2D scaling of the View object around its fulcrum.
  • PivotX and pivotY: These two attributes control the position of the fulcrum around which the View object is rotated and scaled. By default, the position of this fulcrum is the center of the View object.
  • X and Y: These two simple and useful attributes describe the final position of the View object in its container, which is the cumulative sum of the original upper-left coordinate and the translationX and translationY values.
  • Alpha: Indicates the alpha transparency of the View object. The default value is 1 (opaque) and 0 represents full transparency (invisible).

Based on the above, we know that the animation effect of view animation is basically included here.

If a property doesn’t have get and set methods, is there no way to animate the property? The answer is no. Google provides two solutions to solve this problem at the application layer. One is to add get and set methods to this attribute indirectly by customizing an attribute class or wrapping it. ValueAnimator (ValueAnimator, ValueAnimator, ValueAnimator, ValueAnimator, ValueAnimator, ValueAnimator)

private static class WrapperView {
    private View mTarget;

    public WrapperView(View mTarget) {
        this.mTarget = mTarget;
    }

    public int getWidth() {
        return mTarget.getLayoutParams().width;
    }

    public void setWidth(int width) { mTarget.getLayoutParams().width = width; mTarget.requestLayout(); }}Copy the code

With the above code, you wrap a layer around an attribute and provide it with get and set methods. To call the get and set methods, you only need to manipulate the wrapper class, as shown below:

WrapperView wrapperView = new WrapperView(view);
ObjectAnimator.ofInt(wrapperView, "width", 500).setDuration(5000).start();Copy the code

(2) PropertyValuesHolder

Similar to AnimationSet in view animation, PropertyValuesHolder can be used to animate multiple properties of the same object simultaneously in property animation. For example, if the zoom of X and Y axis is changed during the pan animation, it can be implemented like this:

PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(pvh1, pvh2, pvh3).setDuration(1000).start();Copy the code

In the code, the PropertyValuesHolder object controls translationX, scaleX, and scaleY, respectively. The prick call ObjectAnimator. OfPropertyValuesHolder method of multi-attribute animation work together, the whole implementation method is very similar to AnimatorSet use.

(3) ValueAnimator

ValueAnimator plays a very important role in property animation. Although it is not as eye-catching as ObjectAnimator, it is the core of property animation. ObjectAnimator is also inherited from ValueAnimator.

public final class ObjectAnimator extends ValueAnimatorCopy the code

ValueAnimator itself does not provide any animation effects. It is more like a numeric generator that produces regular numbers that allow the caller to control the animation implementation. ValueAnimator’s AnimatorUpdateListener normally listens for numeric transformations to perform animation transformations.

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 100);
valueAnimator.setTarget(imageView);
valueAnimator.setDuration(1000).start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Float value = (Float) animation.getAnimatedValue(); }});Copy the code

(4) Monitoring of animation events

A complete animation has four procedures: Start, Repeat, End, and Cancel. Android provides interfaces to easily listen to these four events:

ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "alpha"0.5 F); 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) {

    }
});
anim.start();Copy the code

Most of the time we only care about the onAnimationEnd event, so Android also provides an AnimatorListenerAdapter that lets us select the necessary events to listen on:

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

(5) AnimatorSet

To animate multiple properties on a property at the same time, we already did this using PropertyValuesHolder. AnimatorSet not only achieves this, but also allows for more precise sequence control. PropertyValuesHolder: AnimatorSet: PropertyValuesHolder: AnimatorSet: AnimatorSet

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "translationX", 300f);
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 0f, 1f);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 0f, 1f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(1000);
animatorSet.playTogether(objectAnimator, objectAnimator1, objectAnimator2);
animatorSet.start();Copy the code

In attribute animations, AnimatorSet controls how many animations work together through playTogether(), playSquentially(), animset.play ().width(), defore(), and after(). In order to achieve accurate control of the animation playback sequence.

(6) Use property animation in XML

Property animations, like view animations, can also be written directly into an XML file:

<? xml version="1.0" encoding="utf-8"? > <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="scaleX"
    android:valueFrom="1.0"
    android:valueTo="2.0"
    android:valueType="floatType">

</objectAnimator>Copy the code

Premise to use XML to define attribute animation XML files must be put in the res/animator/filename. The XML file to identify below, otherwise can’t identify. It turns out that property animations are written similarly to view animations in XML files. Use in a program:

Animator anim = AnimatorInflater.loadAnimator(this,R.animator.filename);
anim.setTarget(view);
anim.start();Copy the code

(7) View animate method

After Android3.0, Google added the animate method to View to drive property animations directly.

imageView.animate()
        .alpha(0)
        .y(300)
        .setDuration(300)
        .withStartAction(new Runnable() {
            @Override
            public void run() {

            }
        })
        .withEndAction(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {}}); } }).start();Copy the code

Android layout animation

Layout animation refers to the effect on the ViewGroup, to add a View to the ViewGroup to add a transition animation effect. The simplest layout animation is in the ViewGroup XML. Open the layout animation with the following code:

android:animateLayoutChanges="true"Copy the code

When a ViewGroup is added to a View, the child View will display a gradual transition effect, but this effect is the default transition effect displayed on Android. There is no way to use custom animation to replace this effect.

You can also customize the transition effect of a child View by using the LayoutAnimatorController class, adding a View animation to make the child View appear with a zoomed animation effect:

LinearLayout ll = (LinearLayout) findViewById(R.id.ll); ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1); sa.setDuration(2000); / / set the layout of the animation display LayoutAnimationController lac = new LayoutAnimationController (sa, 0.5 f); // Set the layout animation ll.setLayoutAnimation(lac);Copy the code

LayoutAnimationController first argument, it is need to the role of the animation, and the second parameter, is each child View shows the delay time. When the delay time is not 0, you can set the display order of sub-views.

Public static final int ORDER_NORMAL = 0; Public static final int ORDER_REVERSE = 1; Public static final int ORDER_RANDOM = 2;Copy the code

Interpolators — Interpolators

Interpolators are an important concept of animation. By Interpolators, we can define the transformation rate of animation, which is similar to acceleration in physics. It mainly controls the change value of a target variable.

  • AccelerateDecelerateInterpolator at the beginning of the animation and introduce the local rate of change is slow, in the middle of acceleration
  • AccelerateInterpolator changes rate slowly at the beginning of an animation, then starts to accelerate
  • Argateinterpolator will be started backwards and then forward
  • AnticipateOvershootInterpolator at the start of the backward and forward to jilt a certain value returns the value of the final
  • BounceInterpolator BounceInterpolator plays at the end of the animation
  • CycleInterpolator animation plays looping a specific number of times, changing the rate along a sine curve
  • Activity Ateinterpolator is fast and slow at the beginning of animation
  • The LinearInterpolator changes at a constant rate
  • OvershootInterpolator throws a value forward before returning to the original position
  • PathInterpolator PathInterpolator

Custom animation

Creating a custom animation requires only the logic of its applyTransformation to be implemented, but typically you also need to override the parent class’s Initalize method for initialization. The applyTransformation method is as follows:

protected void applyTransformation(
        float interpolatedTime,
        Transformation t) {
}Copy the code

The first interpolatedTime parameter is the interpolator’s time factor calculated by the current percentage of animation completion and interpolatedTime corresponding to the plug-in, ranging from 0 to 1.0.

The second argument, Transformation, is the wrapper class for the matrix, which is typically used to obtain the current scenario, as follows:

final Matrix matrix = t.getMatrix();Copy the code

By changing the matrix object obtained, the animation effect can be realized, and the matrix transformation operation can basically achieve any effect of the animation. For an introduction to Matrix, see: In-depth Understanding of Matrix in Android

@Override
protected void applyTransformation(
        floatinterpolatedTime, Transformation t) { final Matrix matrix = t.getMatrix(); // Animation via matrix operations}Copy the code

See how simple matrix changes can be animated by simulating the effect of a TV off. The effect of turning off the TV is to make a picture of the longitudinal scale of continuous shrinking, the corresponding matrix dynamic processing method is as follows:

@Override
protected void applyTransformation(
        float interpolatedTime,
        Transformation t) {
    final Matrix matrix = t.getMatrix();
    matrix.preScale(1,
            1 - interpolatedTime,
            mCenterWidth,
            mCenterHeight);
}Copy the code

MCenterWidth and mCenterHeight are the center points of the zoom, which can be set to the center of the image. Thus, through a simple matrix transformation, you can simulate the animation of the TV set turning off.

You can also set up more accurate interpolators and split the time factors from 0 to 1 into different processes, so that different processes can be animated differently. The code is as follows:

@Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); // Set the default durationsetDuration(2000); // Preserve state after animationsetFillAfter(true); // Set the default interpolatorsetInterpolator(new BounceInterpolator());
    mCenterWidth = width / 2;
    mCenterHeight = height / 2;
}Copy the code

The core of custom animation — how to define the animation process, code:

@Override
protected void applyTransformation(
        floatinterpolatedTime, Transformation t) { final Matrix matrix = t.getMatrix(); mCamera.save(); // Use Camera to set rotation Angle McAmera. rotateY(mRotateY * interpolatedTime); // apply the rotation transform to matrix McAmera. getMatrix(matrix); mCamera.restore(); PreTranslate (mCenterWidth, mCenterHeight); preTranslate(mCenterWidth, mCenterHeight); matrix.postTranslate(-mCenterWidth, -mCenterHeight); }Copy the code

Using the Camera class, you can set the rotation Angle of the three axes. The last two lines of code change the default rotation center.

To be continued…