banner
jzman

jzman

Coding、思考、自觉。
github

Android Property Animation

Previous summarized the relevant knowledge of Android frame animation and tween animation. This article will introduce property animation. Compared to frame animation and tween animation, property animation is more powerful. Frame animation and tween animation can only be applied to View and its subclasses, while property animation can modify the property values of any object. The property values can automatically change over a specified period, allowing for more complex animations based on the changes in the object's property values.

  1. Common settings for property animation
  2. ValueAnimator
  3. ObjectAnimator
  4. Keyframes
  5. Interpolators and evaluators

Common settings for property animation#

Below are the common settings for property animation:

// Set the duration of the property animation
animator.setDuration(2000);
// Set the property interpolator
animator.setInterpolator(new AccelerateInterpolator());
// Set the repeat mode for the property animation
animator.setRepeatMode(ValueAnimator.REVERSE);
// Set the repeat count for the property animation
animator.setRepeatCount(0);
// Set the start delay for the property animation
animator.setStartDelay(0);
// Set the evaluator for the property animation, used to control the final property value (API22)
animator.setCurrentFraction(0.5f);
// Set the current play time, its value is within the Duration range
animator.setCurrentPlayTime(1000);
// Set the evaluator for the property animation, used to control the final property value
animator.setEvaluator(new IntEvaluator());
// Set the property animation listener
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.i(TAG, animation.getAnimatedValue() + "");
        //
    }
});
//...

ValueAnimator#

ValueAnimator provides a simple timing engine to calculate animation values based on the set duration and other properties during animation execution. The calculated animation values can then be set to the appropriate target object. The default interpolator used is AccelerateDecelerateInterpolator, which means the animation starts and ends slowly, accelerating in the middle to complete the animation. Below is the default interpolator from the source code:

// The time interpolator to be used if none is set on the animation
private static final TimeInterpolator sDefaultInterpolator =
        new AccelerateDecelerateInterpolator();

In ValueAnimator, some evaluators like IntEvaluator and FloatEvaluator are already handled internally. This means that if the ofInt and ofFloat methods are used as animation property values, ValueAnimator will automatically handle the changes in int and float values. This part can be found in the PropertyValuesHolder class, as shown below:

void init() {
    if (mEvaluator == null) {
        // We already handle int and float automatically, but not their Object
        // equivalents
        mEvaluator = (mValueType == Integer.class) ? sIntEvaluator :
                (mValueType == Float.class) ? sFloatEvaluator :
                null;
    }
    if (mEvaluator != null) {
        // KeyframeSet knows how to evaluate the common types - only give it a custom
        // evaluator if one has been set on this class
        mKeyframes.setEvaluator(mEvaluator);
    }
}

ValueAnimator can be created using code or XML. Below is an example of using ValueAnimator for translation animation, with similar usage for scaling, rotation, etc.

Creating with code#

private void translation(){
    ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
    valueAnimator.setDuration(2000);
    valueAnimator.setInterpolator(new AccelerateInterpolator());
    valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
    valueAnimator.setRepeatCount(0);
    valueAnimator.setStartDelay(0);
//    valueAnimator.setCurrentFraction(0.5f);
//    valueAnimator.setCurrentPlayTime(1000);
    valueAnimator.setEvaluator(new IntEvaluator());

    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Log.i(TAG, animation.getAnimatedValue() + "");
            int x = (int) animation.getAnimatedValue();
            ivImage.setTranslationX(x);
            ivImage.setTranslationY(x);
        }
    });

    valueAnimator.start();
}

Creating with XML#

Create a test_animator.xml file in the res/animator folder, with the following content:

<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueFrom="0"
    android:valueTo="100"
    android:valueType="intType"

    android:duration="2000"
    android:startOffset ="0"
    android:repeatMode = "reverse"
    android:repeatCount = "0"
    android:interpolator = "@android:anim/accelerate_interpolator">
</animator>

Then, in the Activity, obtain the ValueAnimator, set the target object, and start the animation as follows:

private void translation(){
    ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.test_animator);
    animator.setTarget(ivImage);
    animator.start();
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Log.i(TAG, animation.getAnimatedValue() + "");
            int x = (int) animation.getAnimatedValue();
            ivImage.setTranslationX(x);
            ivImage.setTranslationY(x);
        }
    });
}

Testing effect#

Here, ValueAnimator is used to implement translation animation, with the testing effect as follows:

image

ObjectAnimator#

ObjectAnimator is a subclass of ValueAnimator that supports setting animation properties on the target object. In its constructor, the target object and the corresponding animation property name are specified as parameters, and it will execute the corresponding setter method for the animation property to complete the animation execution. This means that property animation ObjectAnimator ultimately calls the setter method of the target object to change the property value of the target object, thereby achieving the animation effect on the target object. Below is an introduction to the basic usage of ObjectAnimator with opacity change, with the code as follows:

private void alpha(){
    ObjectAnimator animator = ObjectAnimator.ofFloat(ivImage,"alpha",1f,0,1f);
    animator.setDuration(3000);
    // Other property animation settings
    //...
    animator.start();
}

Below is the testing effect, as shown in the following image:

image

As for the implementation methods for translation, rotation, and scaling animations, they are basically the same as above, and will not be elaborated here. The corresponding setter method relationships are as follows:

PropertyFunctionCorresponding Method
AlphaControls the transparency of the ViewsetAlpha
TranslationXControls the displacement in the X directionsetTranslationX
TranslationYControls the displacement in the Y directionsetTranslationY
ScaleXControls the scaling factor in the X directionsetScaleX
ScaleYControls the scaling factor in the Y directionsetScaleY
RotationControls the rotation degree around the screen directionsetRotation
RotationXControls the rotation degree around the X axissetRotationX
RotationYControls the rotation degree around the Y axissetRotationY

ObjectAnimator provides many ofXxx() methods to facilitate setting property animations, as shown in the following image:

image

Different ofXxx() methods of ObjectAnimator can be used according to different animation needs to achieve the corresponding animation.

Keyframes#

Here is a brief introduction to the use of keyframes. As the name suggests, keyframes define specific property values at certain fixed moments. The defined values will return property values according to the values returned by the evaluator. The usage of keyframes in property animation is as follows:

/**
 * Usage of keyframes
 */
private void keyFrame(){
    Keyframe keyframe1 = Keyframe.ofFloat(0,0);
    Keyframe keyframe2 = Keyframe.ofFloat(0.25f,300);
    // Each KeyFrame can set its own interpolator
    keyframe2.setInterpolator(new AccelerateInterpolator());
    Keyframe keyframe3 = Keyframe.ofFloat(0.75f,100);
    Keyframe keyframe4 = Keyframe.ofFloat(1,400);
    PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX",keyframe1,keyframe2,keyframe3,keyframe4);
    ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(ivImage,holder);
    animator.setDuration(3000);
    animator.start();
}

Let's take a look at how adding keyframes changes a regular translation animation, with the testing effect as follows:

image

Interpolators and evaluators#

  • Interpolator (TimeInterpolator) represents the change pattern of the animation throughout its duration, such as acceleration, deceleration, etc.

Android has many built-in interpolators that cover most situations encountered in actual development, as shown below:

image

If the built-in interpolators do not meet your needs, you can also create custom interpolators.

  • Evaluator (TypeEvaluator) represents the specific changes in property values at each moment during the entire animation.

Here is a custom evaluator to implement a View moving along a sine curve, with the custom evaluator as follows:

/**
 * Custom evaluator
 * Point encapsulates coordinates x and y
 */
public class SineTypeValue implements TypeEvaluator<Point> {
    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        // y = sinA
        float distance = fraction * (endValue.getX() - startValue.getX());
        float x = startValue.getX() + distance;
        float y = startValue.getY() + (float) Math.sin(distance / 100 * Math.PI) * 100;
        Point point = new Point();
        point.setX(x);
        point.setY(y);
        return point;
    }
}

Then set this evaluator for the animation, and listen to the animation properties to set the View's position to achieve a View moving along a sine curve, with the usage as follows:

/**
 * Usage of custom evaluator
 * Sine motion evaluator
 */
private void sina(){
    Point startPoint = new Point(ivImage.getX(),ivImage.getY());
    Point endPoint = new Point(ivImage.getX()+500,ivImage.getY());
    ValueAnimator valueAnimator = ValueAnimator.ofObject(new SineTypeValue(), startPoint, endPoint);
    valueAnimator.setDuration(5000);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Log.i(TAG, animation.getAnimatedValue() + "");
            Point point = (Point) animation.getAnimatedValue();
            ivImage.setX(point.getX());
            ivImage.setY(point.getY());
        }
    });
    valueAnimator.start();
}

The testing effect is as follows:

image

The summary of Android property animation ends here.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.