Explosive implementation concept 1. Get the current control background bitmapFor example, imageview is used in the example. For this control, I provideToolTo obtain the Bitmap object of the background.
public static Bitmap createBitmapFromView(View view) { view.clearFocus(); Bitmap bitmap = createBitmapSafely(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888, 1); if (bitmap != null) { synchronized (sCanvas) { Canvas canvas = sCanvas; canvas.setBitmap(bitmap); view.draw(canvas); canvas.setBitmap(null); } } return bitmap; } public static Bitmap createBitmapSafely(int width, int height, Bitmap.Config config, int retryCount) { try { return Bitmap.createBitmap(width, height, config); } catch (OutOfMemoryError e) { e.printStackTrace(); if (retryCount > 0) { System.gc(); return createBitmapSafely(width, height, config, retryCount - 1); } return null; } }
The above method, in short, isCopy the Bitmap object of the control and return it.
We know that,Bitmap can be regarded as a pixel matrix. The vertices above the matrix are color pixels, so we can obtain the color and position of each vertex (not necessarily each, assembled into an object Particle, so that the Particle represents a colored dot.
2. Convert the background bitmap into a Particle ArrayAfter obtaining Bitmap, we hand it over to the participant factory for processing and generate Particle arrays based on Bitmap.
public abstract class ParticleFactory { public abstract Particle[][] generateParticles(Bitmap bitmap, Rect bound);}
For example, let's look at a simple implementation class, which is also the first factory class in gif images with falling effects.
Public class fallingparticipant lefactory extends participant factory {public static final int PART_WH = 8; // default small ball width and height public Particle [] [] generateParticles (Bitmap bitmap, Rect bound) {int w = bound. width (); // scene width int h = bound. height (); // scene height int partW_Count = w/PART_WH; // horizontal number int partH_Count = h/PART_WH; // vertical number int bitmap_part_w = bitmap. getWidth ()/partW_Count; int bitmap_part_h = bitmap. getHeight ()/partH_Count; Particle [] [] participant = new Particle [partH_Count] [partW_Count]; Point point = null; for (int row = 0; row <partH_Count; row ++) {// row for (int column = 0; column <partW_Count; column ++) {// column // obtain the color int color = bitmap where the current particle is located. getPixel (column * bitmap_part_w, row * bitmap_part_h); float x = bound. left + fallingparticipant factory. PART_WH * column; float y = bound. top + fallingparticipant factory. PART_WH * row; participant [row] [column] = new FallingParticle (color, x, y, bound) ;}} return participant ;}}
WhereThe Rect bound represents the width and height of the original View control..
According to eachParticle Size, AndControl width and heightThen we can calculate how many particles constitute the background of the control.
We get the color and position of the position where each particle is located for particle production, which is FallingParticle.
3. generate an explosion site and start the explosion animation process.Site required for ExplosionThat is, the place where the particles are drawn. We add an ExplosionField covering the full screen to the current screen as the explosion site.
Public class ExplosionField extends View {... /*** add full-screen ExplosionField */private void attach2Activity (Activity) {ViewGroup rootView = (ViewGroup) activity to the activity. findViewById (Window. ID_ANDROID_CONTENT); ViewGroup. layoutParams lp = new ViewGroup. layoutParams (ViewGroup. layoutParams. MATCH_PARENT, ViewGroup. layoutParams. MATCH_PARENT); rootView. addView (this, lp );}...}
After the explosion site is added, we respond to the Click Event of the control and start the animation.
FirstAnimation
/*** Brute-force cracking * @ param view causes this view to be cracked */public void explode (final View view) {// prevent repeated click if (explosionAnimatorsMap. get (view )! = Null & explosionAnimatorsMap. get (view ). isStarted () {return;} // to correctly plot the particle final Rect rect = new Rect (); view. getGlobalVisibleRect (rect); // obtain the coordinate int contentTop = (ViewGroup) getParent () of the view relative to the entire screen ()). getTop (); Rect frame = new Rect (); (Activity) getContext ()). getWindow (). getDecorView (). getWindowVisibleDisplayFrame (frame); int statusBarHeight = frame. top; rect. offset (0,-contentTop-statusBarHeight); // remove the status bar height and title bar height. // shake the animation ValueAnimator animator = ValueAnimator. ofFloat (0f, 1f ). setDuration (150); animator. addUpdateListener (new ValueAnimator. animatorUpdateListener () {Random random = new Random (); @ Override public void onAnimationUpdate (ValueAnimator animation) {view. setTranslationX (random. nextFloat ()-0.5f) * view. getWidth () * 0.05f); view. setTranslationY (random. nextFloat ()-0.5f) * view. getHeight () * 0.05f) ;}}); animator. addListener (new AnimatorListenerAdapter () {@ Override public void onAnimationEnd (Animator animation) {super. onAnimationEnd (animation); explode (view, rect); // explosion animation}); animator. start ();}
Vibration animation is very simple, that is, on the x and y directions, random displacement is generated, so that the original control can be moved.
At the end of the animation, an animation explosion was called, and the animation began to explode.
Private void explode (final View view, Rect rect) {final ExplosionAnimator animator = new ExplosionAnimator (this, Utils. createBitmapFromView (view), rect, mParticleFactory); explosionAnimators. add (animator); explosionAnimatorsMap. put (view, animator); animator. addListener (new AnimatorListenerAdapter () {@ Override public void onAnimationStart (Animator animation) {// zoom out and transparent animation view. animate (). setDuration (150 ). scaleX (0f ). scaleY (0f ). alpha (0f ). start () ;}@ Override public void onAnimationEnd (Animator animation) {view. animate (). alpha (1f ). setDuration (150 ). start (); // explosionAnimators are removed from the animation set at the animation end. remove (animation); explosionAnimatorsMap. remove (view); animation = null ;}}); animator. start ();}
Animation explosion firstHide the original control.
Let's look at the specific implementation of the explosion animation.
Public class ExplosionAnimator extends ValueAnimator {... public ExplosionAnimator (View view, Bitmap bitmap, Rect bound, fig factory) {mParticleFactory = participant factory; mPaint = new Paint (); mContainer = view; setFloatValues (0.0f, 1.0f ); setDuration (DEFAULT_DURATION); mParticles = mParticleFactory. generateParticles (bitmap, bound);} // the most important method is public void draw (Canvas canvas ){ If (! IsStarted () {// stop return when the animation ends;} // All Particle Motion for (particle [] Particle: mParticles) {for (particle p: Particle) {p. advance (canvas, mPaint, (Float) getAnimatedValue () ;}} mContainer. invalidate () ;}@ Override public void start () {super. start (); mContainer. invalidate ();}}
The implementation is simple, that is, generating a particle Array Based on the factory class.
The essence is a ValueAnimator, which is counted from 0 to 1 in a certain period of time.
Then a draw () method is provided to callThe advance () method of each particle is used.And input the number of the current count (a decimal number ).
In the advance () method, the draw () method and caculate () method are actually called.
The above implementation,In fact, it is a fixed process. After the explosion site is added, we start to count from 0 to 1. In this process, the particles will draw their own positions based on the current time, therefore, the position of a particle is determined by itself and has nothing to do with the process.
That is to say, we only need to use different algorithms to draw the position of the particle, thus realizing the separation of flow and particle motion.
4. How to exercise? Particles are the clearestFor example, in a gif image, the falling particles are moving like this.
Public class FallingParticle extends Particle {static Random random = new Random (); float radius = fallingparticipant factory. PART_WH; float alpha = 1.0f; Rect mBound;/*** @ param color * @ param x * @ param y */public FallingParticle (int color, float x, float y, rect bound) {super (color, x, y); mBound = bound ;}... protected void caculate (float factor) {cx = cx + factor * random. nextInt (mBound. width () * (random. nextFloat ()-0.5f); cy = cy + factor * random. nextInt (mBound. height ()/2); radius = radius-factor * random. nextInt (2); alpha = (1f-factor) * (1 + random. nextFloat ());}}
The caculate (float factor) method calculates the next position of a particle based on the current time.
We can see that in this particle, cy is increasing in the vertical direction, and cx is also increasing or decreasing randomly in the horizontal direction, thus forming a falling effect.
After calculating the current position, the particle will be drawn by itself.
Protected void draw (Canvas canvas, Paint paint) {paint. setColor (color); paint. setAlpha (int) (Color. alpha (color) * alpha); // The transparent color is not black canvas. drawCircle (cx, cy, radius, paint );}
How to expand?From the code structure, we can see that,The explosion process is irrelevant to the specific motion of particles.And most importantly, we wantImplement your own caculate () method to determine the Particle Motion Form.
Different particles can be produced by the corresponding factory, so the explosion characteristics should be extended,You only need to define a particle class and the factory that generates the particle class.