Android path animation production
1. Preface
Today, the project will use a function similar to sending Dash and screen floating expression. So after analysis and research, the technology used should be path animation, which is incorrect if you do not know it, it is to draw a path line, and then the object moves according to the path. So we call it path animation.
The first problem to be solved for path animation is how to draw the path? After the path is drawn, how do I obtain the coordinates of all vertices in the path?
To solve these two problems, we can see that the PathMeasure class receives a path object, and then we can obtain the coordinate value of the length ratio according to pathMeasure. getPosTan. These two problems are solved directly. Use path to draw a path, then take the vertex, and dynamically move the object to a path animation. Is it easy.
2. view results
3. Core code
/The knowledge points used by * ** flowers ** @ author yd: 1. android property Animation 2. Path rendering 3. besserx curve *********/public class FllowerAnimation extends View implements AnimatorUpdateListener {/***** the property value changed by the animation */private float phase1 = 0f; private float phase2 = 0f; private float phase3 = 0f;/*** small ball set */private List
Fllowers1 = new ArrayList
(); Private List
Fllowers2 = new ArrayList
(); Private List
Fllowers3 = new ArrayList
();/*** Animation playback time */private int time = 4000;/***** animation interval */private int delay = 500; /*** resource ID * // private int resId = R. drawable. fllower_love; public FllowerAnimation (Context context) {super (context); init (context); // this. resId = resId ;}@ SuppressWarnings (deprecation) private void init (Context context) {WindowManager wm = (WindowManager) context. getSystemService (Context. WINDOW_SERVICE); width = wm. getdefadisplay display (). getWidth (); height = (int) (wm. getdefadisplay display (). getHeight () * 3/2f); mPaint = new Paint (); mPaint. setAntiAlias (true); mPaint. setStrokeWidth (2); mPaint. setColor (Color. BLUE); mPaint. setStyle (Style. STROKE); pathMeasure = new PathMeasure (); builderFollower (fllowerCount, fllowers1); builderFollower (fllowerCount, fllowers2); builderFollower (fllowerCount, fllowers3 );} /***** width */private int width = 0;/***** height */private int height = 0; /***** split the number of curve heights */private int quadCount = 10;/***** curvature */private float intensity = 0.2f; /*** number of the first batch */private int fllowerCount = 4;/***** create flowers */private void builderFollower (int count, List
Fllowers) {int max = (int) (width * 3/4f); int min = (int) (width/4f); Random random = new Random (); for (int I = 0; I <count; I ++) {int s = random. nextInt (max) % (max-min + 1) + min; Path path = new Path (); CPoint = new CPoint (s, 0); List
Points = builderPath (CPoint); drawFllowerPath (path, points); Fllower fllower = new Fllower (); fllower. setPath (path); fllowers. add (fllower) ;}}/*** draw curve * @ param path * @ param points */private void drawFllowerPath (Path path, List
Points) {if (points. size ()> 1) {for (int j = 0; j <points. size (); j ++) {CPoint point = points. get (j); if (j = 0) {CPoint next = points. get (j + 1); point. dx = (next. x-point. x) * intensity); point. dy = (next. y-point. y) * intensity);} else if (j = points. size ()-1) {CPoint prev = points. get (j-1); point. dx = (point. x-prev. x) * intensity); point. dy = (point. y-prev. y) * intensity);} else {CPoint next = points. get (j + 1); CPoint prev = points. get (j-1); point. dx = (next. x-prev. x) * intensity); point. dy = (next. y-prev. y) * intensity);} // create the cubic-spline patlif (j = 0) {path. moveTo (point. x, point. y);} else {CPoint prev = points. get (j-1); path. cubicTo (prev. x + prev. dx, (prev. y + prev. dy), point. x-point. dx, (point. y-point. dy), point. x, point. y) ;}}}/*** curve swing margin */private int range = (int) TypedValue. applyDimension (TypedValue. COMPLEX_UNIT_DIP, 70, getResources (). getDisplayMetrics ();/** draw path ** @ param point * @ return */private List
BuilderPath (CPoint point) {List
Points = new ArrayList
(); Random random = new Random (); for (int I = 0; I <quadCount; I ++) {if (I = 0) {points. add (point);} else {CPoint tmp = new CPoint (0, 0); if (random. nextInt (100) % 2 = 0) {tmp. x = point. x + random. nextInt (range);} else {tmp. x = point. x-random. nextInt (range);} tmp. y = (int) (height/(float) quadCount * I); points. add (tmp) ;}} return points;}/*** Paint brush */private Paint mPaint;/*** Coordinate Position of the measurement path */private PathMeasure pathMeasure = null; @ Overrideprotected void onDraw (Canvas canvas) {super. onDraw (canvas); drawFllower (canvas, fllowers1); drawFllower (canvas, fllowers2); drawFllower (canvas, fllowers3);}/*** the height up offset, remove the start point from the top of the screen */private float dy = TypedValue. applyDimension (TypedValue. COMPLEX_UNIT_DIP, 40, getResources (). getDisplayMetrics ();/***** @ param canvas * @ param fllowers */private void drawFllower (Canvas canvas, List
Fllowers) {for (Fllower fllower: fllowers) {float [] pos = new float [2]; canvas. drawPath (fllower. getPath (), mPaint); pathMeasure. setPath (fllower. getPath (), false); pathMeasure. getPosTan (height * fllower. getValue (), pos, null); canvas. drawCircle (pos [0], pos [1], 10, mPaint); // Bitmap bitmap = BitmapFactory. decodeResource (getResources (), resId); // canvas. drawBitmap (bitmap, pos [0], pos [1]-dy, null); // bitmap. recycle () ;}} public void startAnimation () {ObjectAnimator mAnimator1 = ObjectAnimator. ofFloat (this, phase1, 0f, 1f); mAnimator1.setDuration (time); random (this); mAnimator1.start (); random (new random (1f); ObjectAnimator mAnimator2 = ObjectAnimator. ofFloat (this, phase2, 0f, 1f); mAnimator2.setDuration (time); hour (this); mAnimator2.start (); hour (new AccelerateInterpolator (1f); hour (delay ); objectAnimator mAnimator3 = ObjectAnimator. ofFloat (this, phase3, 0f, 1f); mAnimator3.setDuration (time); Combine (this); mAnimator3.start (); mAnimator3.setInterpolator (new AccelerateInterpolator (1f )); mAnimator3.setStartDelay (delay * 2);}/*** match the position of the new ball ** @ param value * @ param fllowers */private void updateValue (float value, List
Fllowers) {for (Fllower fllower: fllowers) {fllower. setValue (value) ;}}/*** animation change callback */@ Overridepublic void onAnimationUpdate (ValueAnimator arg0) {updateValue (getPhase1 (), fllowers1); updateValue (getPhase2 (), fllowers2); updateValue (getPhase3 (), fllowers3); Log. I (tag, getPhase1 () +); invalidate ();} public float getPhase1 () {return phase1;} public void setPhase1 (float phase1) {this. phase1 = phase1;} public float getPhase2 () {return phase2;} public void setPhase2 (float phase2) {this. phase2 = phase2;} public float getPhase3 () {return phase3;} public void setPhase3 (float phase3) {this. phase3 = phase3;} private String tag = this. getClass (). getSimpleName (); private class CPoint {public float x = 0f; public float y = 0f;/** x-axis distance */public float dx = 0f; /** y-axis distance */public float dy = 0f; public CPoint (float x, float y) {this. x = x; this. y = y ;}}}