An article gives you a detailed explanation of the animation estimator

An article gives you a detailed explanation of the animation estimator

[[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

  1. ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "height" , new Evaluator(), 1, 3);
  2. // Pass in the object of the corresponding estimator class in the fourth parameter
  3. // There are 3 built-in estimators in the system:
  4. // IntEvaluator: Transition from initial value - end value in integer form
  5. // FloatEvaluator: Transition from initial value - end value in floating point form
  6. // ArgbEvaluator: Transition from initial value - end value in the form of Argb type
  7. Point interpolator: FloatEvaluator
  8. public class FloatEvaluator implements TypeEvaluator {
  9. // FloatEvaluator implements the TypeEvaluator interface
  10. // Rewrite evaluate()
  11. public Object evaluate( float fraction, Object startValue, Object endValue) {
  12. // Parameter description
  13. // fraction: indicates the degree of animation completion (based on which the current animation value is calculated)
  14. // startValue, endValue: the initial value and end value of the animation
  15. float startFloat = ((Number) startValue).floatValue();
  16. return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
  17. // The algorithm for transitioning from initial value to final value is:
  18. // 1. Subtract the initial value from the final value to calculate the difference between them
  19. // 2. Multiply the above difference by the fraction coefficient
  20. // 3. Add the initial value to get the current animation value
  21. }
  22. }
  • 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()
  1. public interface TypeEvaluator {
  2. public Object evaluate( float fraction, Object startValue, Object endValue) {
  3. // Parameter description
  4. // fraction: the return value of the interpolator getInterpolation()
  5. // startValue: the initial value of the animation
  6. // endValue: the end value of the animation
  7. ....//Calculation logic of the estimator
  8. return xxx;
  9. // Specific values ​​assigned to animation properties
  10. // Use reflection mechanism to change property changes
  11. // Special attention
  12. // So what is the relationship between the interpolator input value and the estimator fraction?
  13. // 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.
  14. }
  15. }
  16. // Implement the TypeEvaluator interface
  17. public class ObjectEvaluator implements TypeEvaluator{
  18. // Override evaluate()
  19. // Write the logic of object animation transition in evaluate()
  20. @Override
  21. public Object evaluate( float fraction, Object startValue, Object endValue) {
  22. // Parameter description
  23. // fraction: indicates the degree of animation completion (based on which the current animation value is calculated)
  24. // startValue, endValue: the initial value and end value of the animation
  25. ... // Write the logic of object animation transition
  26. return value;
  27. // Returns the logically calculated value of the object animation transition
  28. }

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;

  1. public class Point {
  2. // Set two variables to record the coordinates
  3. private float x;
  4. private float y;
  5. //Constructor used to set coordinates
  6. public Point( float x, float y) {
  7. this.x = x;
  8. this.y = y;
  9. }
  10. // The get method is used to obtain coordinates
  11. public   float getX() {
  12. return x;
  13. }
  14. public   float getY() {
  15. return y;
  16. }
  17. }

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

  1. public class PointEvaluator implements TypeEvaluator {
  2. // Override evaluate()
  3. // Write the logic of object animation transition in evaluate()
  4. @Override
  5. public Object evaluate( float fraction, Object startValue, Object endValue) {
  6. // Convert the animation initial value startValue and the animation end value endValue into Point objects
  7. Point startPoint = (Point) startValue;
  8. Point endPoint = (Point) endValue;
  9. // Calculate the x and y values ​​of the current animation based on the fraction
  10. float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());
  11. float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
  12. // Encapsulate the calculated coordinates into a new Point object and return
  13. Point point = new Point(x, y);
  14. return point;
  15. }
  16. }

3.3 Attribute animation applied to custom View

  1. public class MyView extends View {
  2. // Set the variables you need
  3. public   static final float RADIUS = 70f; // radius of the circle = 70
  4. private Point currentPoint; // Current point coordinates
  5. private Paint mPaint; // Drawing brush
  6. //Construction method (initialize the brush)
  7. public MyView(Context context, AttributeSet attrs) {
  8. super(context, attrs);
  9. // Initialize the brush
  10. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  11. mPaint.setColor(Color.BLUE);
  12. }
  13. // Override onDraw() to implement drawing logic
  14. // 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
  15. @Override
  16. protected void onDraw(Canvas canvas) {
  17. // If the current point coordinates are empty (i.e. the first time)
  18. if (currentPoint == null ) {
  19. currentPoint = new Point(RADIUS, RADIUS);
  20. // Create a point object (coordinates are (70,70))
  21. // Draw a circle at this point: center = (70,70), radius = 70
  22. float x = currentPoint.getX();
  23. float y = currentPoint.getY();
  24. canvas.drawCircle(x, y, RADIUS, mPaint);
  25. // (Focus on) Applying property animation to View
  26. // Step 1: Create the object point at the beginning of the animation & the object point at the end of the animation
  27. Point startPoint = new Point(RADIUS, RADIUS); // The initial point is the center of the circle (70,70)
  28. Point endPoint = new Point(700, 1000); // The end point is (700, 1000)
  29. // Step 2: Create animation object & set initial value and end value
  30. ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);
  31. // Parameter description
  32. // Parameter 1: TypeEvaluator type parameter - use custom PointEvaluator (implements TypeEvaluator interface)
  33. // Parameter 2: the object point of the initial animation
  34. // Parameter 3: The object point where the animation ends
  35. // Step 3: Set animation parameters
  36. anim.setDuration(5000);
  37. // Set the animation duration
  38. // Step 3: Manually assign the changed object to the current object through the update listener of value
  39. // Here is to assign the changed coordinate value object to the current coordinate value object
  40. // Set the update listener for the value
  41. // That is, every time the coordinate value (Point object) is updated, this method will be called once
  42. anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  43. @Override
  44. public void onAnimationUpdate(ValueAnimator animation) {
  45. currentPoint = (Point) animation.getAnimatedValue();
  46. //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)
  47. //So as to update the current coordinate value (currentPoint)
  48. // Step 4: Redraw after each assignment to achieve animation effect
  49. invalidate();
  50. // After calling invalidate(), the View will be refreshed , so that the redrawn interface can be seen, that is, onDraw() will be called again
  51. // So every time the coordinate value changes, onDraw() will be called once
  52. }
  53. });
  54. anim.start();
  55. // Start the animation
  56. } else {
  57. // If the coordinate value is not 0, draw a circle
  58. // So every time the coordinate value changes, onDraw() will be called once and a circle will be drawn, thus achieving the animation effect
  59. // Draw a circle at this point: center = (30,30), radius = 30
  60. float x = currentPoint.getX();
  61. float y = currentPoint.getY();
  62. canvas.drawCircle(x, y, RADIUS, mPaint);
  63. }
  64. }
  65. }

<<:  iOS 15.2 new feature: can display accessory replacement status

>>:  Is WeChat's web version of Transfer Assistant really useful? It's completely outclassed by AirDroid

Recommend

Transparent glass is "outdated", color-changing glass is here!

Produced by: Science Popularization China Author:...

The oldest vertebrate on Earth has been identified! It also has a "photo" →

The evolution of vertebrates is one of the most m...

Hairline is not stable? Eating right may help you change it!

When people reach middle age, nothing is easy, bu...

APP promotion tips: What do we do before the APP goes online?

Nowadays, people tend to divide product operation...

Does sleeping more when you have a cold really help?

After being infected with the Omicron strain of t...

90% of people don’t know how to do user research. Do you?

Do you really understand user research? Can you d...