[[442626]] Preface TypeEvaluator is translated into Chinese as type valuation algorithm, also called estimator. Its function is to calculate the changed attribute value according to the percentage of the current attribute change. The system presets are IntEvaluator (for integer attributes), FloatEvaluator (for floating-point data) and ArgbEvaluator (for Color attributes); The interpolator and type evaluator in attribute animation are very important. They are important means to achieve non-uniform animation. We have already talked about interpolators before, today we will introduce estimators; 1. Detailed explanation of the estimator 1. Application scenarios- The interpolator determines the law of value change (uniform speed, acceleration, etc.), that is, the trend of change, and the specific change value is handed over to the estimator;
- Properties specific to property animation;
- Non-linear motion: The rate of change of animation is not constant, such as acceleration and deceleration motion are non-linear motion;
2. Specific use 2.1. Setting method - ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "height" , new Evaluator(), 1, 3);
- // Pass in the object of the corresponding estimator class in the fourth parameter
- // There are 3 built-in estimators in the system:
- // IntEvaluator: Transition from initial value - end value in integer form
- // FloatEvaluator: Transition from initial value - end value in floating point form
- // ArgbEvaluator: Transition from initial value - end value in the form of Argb type
- Point interpolator: FloatEvaluator
- public class FloatEvaluator implements TypeEvaluator {
- // FloatEvaluator implements the TypeEvaluator interface
- // Rewrite evaluate()
- public Object evaluate( float fraction, Object startValue, Object endValue) {
- // Parameter description
- // fraction: indicates the degree of animation completion (based on which the current animation value is calculated)
- // startValue, endValue: the initial value and end value of the animation
- float startFloat = ((Number) startValue).floatValue();
- return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
- // The algorithm for transitioning from initial value to final value is:
- // 1. Subtract the initial value from the final value to calculate the difference between them
- // 2. Multiply the above difference by the fraction coefficient
- // 3. Add the initial value to get the current animation value
- }
- }
- ValueAnimator.ofInt() & ValueAnimator.ofFloat() in property animation both have built-in estimators, namely FloatEvaluator & IntEvaluator;
- That is, the system has implemented the logic of how to transition from the initial value to the end value by default;
2.2 Custom Estimator - Essence: Calculate the specific value of the current attribute by calculating the percentage of change of the current attribute value & the initial value & the end value according to the interpolator;
- Specific use: Custom estimator needs to implement TypeEvaluator interface & override evaluate()
- public interface TypeEvaluator {
- public Object evaluate( float fraction, Object startValue, Object endValue) {
- // Parameter description
- // fraction: the return value of the interpolator getInterpolation()
- // startValue: the initial value of the animation
- // endValue: the end value of the animation
- ....//Calculation logic of the estimator
- return xxx;
- // Specific values assigned to animation properties
- // Use reflection mechanism to change property changes
- // Special attention
- // So what is the relationship between the interpolator input value and the estimator fraction?
- // The value of input determines the value of fraction: the input value is calculated and passed to the interpolator getInterpolation(), and then the logical algorithm in getInterpolation() is implemented to calculate a return value based on the input value, and this return value is fraction.
- }
- }
- // Implement the TypeEvaluator interface
- public class ObjectEvaluator implements TypeEvaluator{
- // Override evaluate()
- // Write the logic of object animation transition in evaluate()
- @Override
- public Object evaluate( float fraction, Object startValue, Object endValue) {
- // Parameter description
- // fraction: indicates the degree of animation completion (based on which the current animation value is calculated)
- // startValue, endValue: the initial value and end value of the animation
- ... // Write the logic of object animation transition
- return value;
- // Returns the logically calculated value of the object animation transition
- }
3. Custom Estimator - ValueAnimator.ofObject(), from the working principle, it can be seen that there is no default implementation of the system estimator, because the animation operation of the object is complex and diverse, and the system cannot know how to transition from the initial object to the end object;
- Therefore, for ValueAnimator.ofObject(), we need to customize the estimator (TypeEvaluator) to tell the system how to perform the logic of transitioning from the initial object to the final object;
3.1 Defining Objects Because ValueAnimator.ofObject() is object-oriented, a custom object class is required; - public class Point {
- // Set two variables to record the coordinates
- private float x;
- private float y;
- //Constructor used to set coordinates
- public Point( float x, float y) {
- this.x = x;
- this.y = y;
- }
- // The get method is used to obtain coordinates
- public float getX() {
- return x;
- }
- public float getY() {
- return y;
- }
- }
3.2 Implementing the TypeEvaluator interface The purpose of implementing the TypeEvaluator interface is to customize how to transition from the initial point coordinates to the end point coordinates; This example implements a coordinate transition logic from the upper left corner to the lower right corner. // Implement the TypeEvaluator interface - public class PointEvaluator implements TypeEvaluator {
- // Override evaluate()
- // Write the logic of object animation transition in evaluate()
- @Override
- public Object evaluate( float fraction, Object startValue, Object endValue) {
- // Convert the animation initial value startValue and the animation end value endValue into Point objects
- Point startPoint = (Point) startValue;
- Point endPoint = (Point) endValue;
- // Calculate the x and y values of the current animation based on the fraction
- float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
- float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
- // Encapsulate the calculated coordinates into a new Point object and return
- Point point = new Point(x, y);
- return point;
- }
- }
3.3 Attribute animation applied to custom View - public class MyView extends View {
- // Set the variables you need
- public static final float RADIUS = 70f; // radius of the circle = 70
- private Point currentPoint; // Current point coordinates
- private Paint mPaint; // Drawing brush
- //Construction method (initialize the brush)
- public MyView(Context context, AttributeSet attrs) {
- super(context, attrs);
- // Initialize the brush
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPaint.setColor(Color.BLUE);
- }
- // Override onDraw() to implement drawing logic
- // Drawing logic: Draw a circle at the initial point first, monitor the changes of the current coordinate value (currentPoint), and call onDraw() to redraw the circle every time it changes, so as to achieve the translation effect of the circle
- @Override
- protected void onDraw(Canvas canvas) {
- // If the current point coordinates are empty (i.e. the first time)
- if (currentPoint == null ) {
- currentPoint = new Point(RADIUS, RADIUS);
- // Create a point object (coordinates are (70,70))
- // Draw a circle at this point: center = (70,70), radius = 70
- float x = currentPoint.getX();
- float y = currentPoint.getY();
- canvas.drawCircle(x, y, RADIUS, mPaint);
- // (Focus on) Applying property animation to View
- // Step 1: Create the object point at the beginning of the animation & the object point at the end of the animation
- Point startPoint = new Point(RADIUS, RADIUS); // The initial point is the center of the circle (70,70)
- Point endPoint = new Point(700, 1000); // The end point is (700, 1000)
- // Step 2: Create animation object & set initial value and end value
- ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
- // Parameter description
- // Parameter 1: TypeEvaluator type parameter - use custom PointEvaluator (implements TypeEvaluator interface)
- // Parameter 2: the object point of the initial animation
- // Parameter 3: The object point where the animation ends
- // Step 3: Set animation parameters
- anim.setDuration(5000);
- // Set the animation duration
- // Step 3: Manually assign the changed object to the current object through the update listener of value
- // Here is to assign the changed coordinate value object to the current coordinate value object
- // Set the update listener for the value
- // That is, every time the coordinate value (Point object) is updated, this method will be called once
- anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- currentPoint = (Point) animation.getAnimatedValue();
- //Add the coordinate value after each change (the Piont object value returned by evaluate() in the estimator PointEvaluator) to the current coordinate value object (currentPoint)
- //So as to update the current coordinate value (currentPoint)
- // Step 4: Redraw after each assignment to achieve animation effect
- invalidate();
- // After calling invalidate(), the View will be refreshed , so that the redrawn interface can be seen, that is, onDraw() will be called again
- // So every time the coordinate value changes, onDraw() will be called once
- }
- });
- anim.start();
- // Start the animation
- } else {
- // If the coordinate value is not 0, draw a circle
- // So every time the coordinate value changes, onDraw() will be called once and a circle will be drawn, thus achieving the animation effect
- // Draw a circle at this point: center = (30,30), radius = 30
- float x = currentPoint.getX();
- float y = currentPoint.getY();
- canvas.drawCircle(x, y, RADIUS, mPaint);
- }
- }
- }
|