Android special effects album (6)-imitation QQ chat special effects, invisible installation force, the most fatal
Android special effects album (6)-imitation QQ chat special effects, invisible installation force, the most fatal
In the future, the special effect album I wrote will also be added to this column. The special effect I wrote today is about chatting. You must have met it when you chat with others, for example, sending an application (What?), and then the screen is all emoticon, today we are doing this, the special effects of flowers, international practices,
To achieve this effect, you need to know what the besell curve is? It's actually a curve. Hey hey, you can go to the concept of a curve.
Android plotting mechanism (II) -- coordinate explanations of custom View shapes, circles, triangles, slices, ovans, curves, text and images
Let's take a look at it and we will write it directly here.
1. activity_main.xml
<Code class = "hljs xml"> <relativelayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com/tools" android: layout_width = "match_parent" android: layout_height = "match_parent"> // The sprinkling area <relativelayout android: id = "@ + id/rlt_animation_layout" android: layout_width = "match_parent" android: layout_height = "match_parent"> </relativelayout> </code> <button android: id = "@ + id/btn_start" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_alignparentbottom = "true" android: layout_centerhorizontal = "true" android: layout_marginbottom = "23dp" android: text = "Start sprinkling"> <code class = "hljs xml"> </code> </button>
2. Fllower
Parameter transfer
package com.lgl.test;import android.graphics.Bitmap;import android.graphics.Path;import java.io.Serializable;public class Fllower implements Serializable { private static final long serialVersionUID = 1L; private Bitmap image; private float x; private float y; private Path path; private float value; public Bitmap getResId() { return image; } public void setResId(Bitmap img) { this.image = img; } public float getX() { return x; } public void setX(float x) { this.x = x; } public float getY() { return y; } public void setY(float y) { this.y = y; } public Path getPath() { return path; } public void setPath(Path path) { this.path = path; } public float getValue() { return value; } public void setValue(float value) { this.value = value; } @Override public String toString() { return "Fllower [ x=" + x + ", y=" + y + ", path=" + path + ", value=" + value + "]"; }}
3. FllowerAnimation
Animation
Package com. lgl. test; import java. util. arrayList; import java. util. list; import java. util. random; import android. animation. objectAnimator; import android. animation. valueAnimator; import android. animation. valueAnimator. animatorUpdateListener; import android. content. context; import android. graphics. bitmap; import android. graphics. bitmapFactory; import android. graphics. canvas; import android. graphics. paint; import android. graphics. path; import android. graphics. pathMeasure; import android. util. log; import android. util. typedValue; import android. view. view; import android. view. windowManager; import android. view. animation. accelerateInterpolator;/*** knowledge points used for spreading flowers: 1. android property Animation 2. Path rendering 3. beiser curve */public class FllowerAnimation extends View implements AnimatorUpdateListener {/*** animation-changed attribute value */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 = 400; int [] ylocations = {-100,-50,-25, 0};/*** 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, ylocations [random. nextInt (3)]); List
Points = builderPath (CPoint); drawFllowerPath (path, points); Fllower fllower = new Fllower (); fllower. setPath (path); Bitmap bitmap = BitmapFactory. decodeResource (getResources (), R. drawable. lift_flower); fllower. setResId (bitmap); 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 path if (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; @ Override protected 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); canvas. drawBitmap (fllower. getResId (), pos [0], pos [1]-dy, null) ;}} ObjectAnimator mAnimator1; ObjectAnimator mAnimato R2; ObjectAnimator mAnimator3; public void startAnimation () {if (mAnimator1! = Null & mAnimator1.isRunning () {mAnimator1.cancel ();} mAnimator1 = ObjectAnimator. ofFloat (this, "phase1", 0f, 1f); mAnimator1.setDuration (time); hour (this); mAnimator1.start (); hour (new AccelerateInterpolator (1f); if! = Null & mAnimator2.isRunning () {mAnimator2.cancel ();} mAnimator2 = ObjectAnimator. ofFloat (this, "phase2", 0f, 1f); mAnimator2.setDuration (time); Combine (this); mAnimator2.start (); mAnimator2.setInterpolator (new AccelerateInterpolator (1f )); mAnimator2.setStartDelay (delay); if (mAnimator3! = Null & mAnimator3.isRunning () {mAnimator3.cancel ();} 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 */@ Override public 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 ;}}}
4. MainActivity
Next, let's see how we use
Package com. lgl. test; import android. app. activity; import android. OS. bundle; import android. view. view; import android. view. view. onClickListener; import android. widget. button; import android. widget. relativeLayout; public class MainActivity extends Activity {private Button btn_start; // private RelativeLayout effect; private parameter FllowerAnimation; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); // initialize rlt_animation_layout = (RelativeLayout) findViewById (R. id. rlt_animation_layout); rlt_animation_layout.setVisibility (View. VISIBLE); fllowerAnimation = new FllowerAnimation (this); RelativeLayout. layoutParams params = new RelativeLayout. layoutParams (RelativeLayout. layoutParams. MATCH_PARENT, RelativeLayout. layoutParams. MATCH_PARENT); fllowerAnimation. setLayoutParams (params); rlt_animation_layout.addView (fllowerAnimation); btn_start = (Button) findViewById (R. id. btn_start); btn_start.setOnClickListener (new OnClickListener () {@ Override public void onClick (View v) {// start to scatter fllowerAnimation. startAnimation ();}});}}
Okay. Now let's take a look at the effect.
Okay. You can try it now!