A few days ago on Weibo by a very good Android open source Components Brush screen-Explosionfield, the effect is very cool, a bit like MIUI uninstall the APP when the animation, first to feel.
650) this.width=650; "src=" Https://github.com/tyrantgit/ExplosionField/raw/master/explosionfield.gif "title=" "/ >
Explosionfield not only the effect of the wind, the code is also very good, so people can not help but to take a good read.
Create Explosionfield
ExplosionField
Inherit from View
, onDraw
draw an animated effect in the method, and it provides a attach2Window
way to add the ExplosionField
most child view to the root view on the Activity.
public static Explosionfield Attach2window (activity activity) {ViewGroup Rootview = (viewgroup) Activity.findviewbyid ( Window.id_android_content); Explosionfield Explosionfield = new Explosionfield (activity); Rootview.addview (Explosionfield, New Viewgroup.layoutparams (ViewGroup.LayoutParams.MATCH_PARENT, Viewgroup.lay Outparams.match_parent)); return Explosionfield;} 1234567
explosionField
LayoutParams
properties are set to MATCH_PARENT
,
In this way, a view exploding particle can be plotted in the area where the Activity is located.
Knowledge Point: You can use window.id_android_content to replace ANDROID. R.id.content
The effect of shaking before exploding
In the view's click event, after the call mExplosionField.explode(v)
, the view vibrates first and then burst.
The vibration effect is relatively simple, set a [0, 1] interval valueanimator, and then AnimatorUpdateListener
onAnimationUpdate
randomly translate the x and Y coordinates in the, and finally the scale and alpha value dynamically reduced to 0.
int startdelay = 100; Valueanimator animator = Valueanimator.offloat (0f, 1f). Setduration, 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.start (); View.animate (). Setduration (Startdelay). Setstartdelay ScaleX (0f). ScaleY (0f). Alpha (0f) . Start (); 123456789101112131415
Create a bitmap based on View
When the View vibrates, it begins with the hardest burst, and the burst is carried out in parallel with the hidden one, first look at the exploding API- void explode(Bitmap bitmap, Rect bound, long startDelay, long duration)
:
The first two parameters bitmap and bound are key, and it's interesting to create bitmap code with View.
If View is a ImageView, and its drawable is a bitmapdrawable you can get the Bitmap directly.
if (view instanceof ImageView) {drawable drawable = ((ImageView) view). Getdrawable (); if (drawable! = null && drawable instanceof bitmapdrawable) {return ((bitmapdrawable) drawable). Getbitmap ( ); }}123456
If it is not a ImageView, you can create a bitmap by following these steps:
Create a new Canvas
Creates an empty bitmap based on the size of the View
Set the empty bitmap as the canvas's base cloth
Draw the view on the canvas
Set the canvas's bitmap to NULL
Of course, the focus of the view should be cleared before drawing, because the focus may change the UI state of a view.
The Scanvas used in the code is a static variable, which saves the overhead of each creation.
View.clearfocus (); Bitmap Bitmap = createbitmapsafely (View.getwidth (), View.getheight (), Bitmap.Config.ARGB_8888, 1); if (Bitmap! = nul L) {synchronized (Scanvas) {Canvas canvas = Scanvas; Canvas.setbitmap (bitmap); View.draw (canvas); Canvas.setbitmap (NULL); }}1234567891011
The author's approach to creating bitmaps is ingenious, and if you create an OOM when you create a new Bitmap, you can proactively do GC-and System.gc()
then try to create it again.
The way this function is implemented makes people admire the author's skill.
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; }}123456789101112
Out of the bitmap, there is also a very important parameter bound, it is relatively simple to create:
Rect r = new rect (); View.getglobalvisiblerect (R); int[] location = new Int[2];getlocationonscreen (location); R.offset (- Location[0],-location[1]); R.inset (-mexpandinset[0],-mexpandinset[1]); 123456
First get the global viewable area of the view that needs to burst--and Rect r
then, by getting the getLocationOnScreen(location)
ExplosionField
coordinates in the screen and panning the visible area of the exploded view According to this coordinate, the burst effect appears in the ExplosionField
, and then extend it according to the Mexpandinset value (default is 0).
What is the use of the bitmap and bound created? We continue to analyze.
Creating particles
Let's take a look at the whole picture of this method of exploding into particles:
public void explode (Bitmap bitmap, rect bound, long startdelay, long duration) { final ExplosionAnimator Explosion = new explosionanimator (This, bitmap, bound); Explosion.addlistener (New animatorlisteneradapter () { @Override public void onanimationend (Animator animation) { Mexplosions.remove (animation); } }); explosion.setstartdelay (Startdelay); explosion.setduration ( Duration); mexplosions.add (explosion); explosion.start ();} 12345678910111213
Here's an explanation of why a container class variable-- mExplosions
to save one ExplosionAnimator
. Because the explosion effect of multiple view in activity may have to be done at the same time, so the burst animation of each view corresponding to save, and so on when the end of the animation deleted.
The author customizes a class that inherits from Valueanimator-Explosionanimator, which mainly does two things, one is to create particles- generateParticle
and the other is to draw particles- draw(Canvas canvas)
.
Let's take a look at the constructor:
Public explosionanimator (View container, bitmap bitmap, rect bound) { mpaint = new paint (); mbound = new rect (bound); int partlen = 15; mparticles = new Particle[partLen * partLen]; Random random = New random (System.currenttimemillis ()); int w = bitmap.getwidth () / (PARTLEN&NBSP;+&NBSP;2); int h = bitmap.getheight () / (PARTLEN&NBSP;+&NBSP;2); for (int i = 0; i < partlen; i++) { for (int j = 0; j < partlen; j++) { mparticles[(I * partlen) + j] = generateparticle (Bitmap.getpixel (j + 1) * w, (i + 1) * h), random); } } mContainer = container; Setfloatvalues (0f, end_value); setinterpolator (Default_interpolator); setduration (default_duration);} 123456789101112131415161718
According to the constructor, it is known that the author divides the bitmap into a matrix of x 17, and the width and height of each element are respectively w
h
.
int w = bitmap.getwidth ()/(Partlen + 2), int h = bitmap.getheight ()/(Partlen + 2); 12
All particles are a matrix of x 15, and the meta-plain value is the pixel value of the bitmap.
Bitmap.getpixel ((j + 1) * W, (i + 1) * h) 1
The structure is shown, where the hollow part is the particle.
&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 &NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0&NBSP;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 &NBSP;
generateParticle
A particle is randomly generated based on a certain algorithm. This part is more cumbersome, analysis omitted.
One of the more ingenious is its draw method:
Public boolean draw (Canvas canvas) { if (!isstarted ()) { return false; } for (particle particle : mparticles) { particle.advance (float) getanimatedvalue ()); if (particle.alpha > 0f) { mpaint.setcolor (Particle.color); mpaint.setalpha ((int) (Color.alpha (Particle.color) * particle.alpha)); canvas.drawcircle (particle.cx, particle.cy, Particle.radius, mpaint); } } mcoNtainer.invalidate (); return true;} 123456789101112131415
At first I was still confused, since the drawing of particles is in ExplosionField
the onDraw
method, it must be constantly refreshed, the results of the author does not do so, the implementation of the method is truly amazing.
First, the author ExplosionAnimator
overloads the method in the class start()
and calls mContainer.invalidate(mBound)
to refresh the chunk corresponding to the View that will explode.
@Overridepublic void Start () {Super.start (); Mcontainer.invalidate (Mbound);} 12345
And Mcontainer is the view that fills the activity--the ExplosionField
method in which it is onDraw
called ExplosionAnimator
draw
.
@Overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas); for (Explosionanimator explosion:mexplosions) {explosion.draw (canvas); }}1234567
The
Then forms a recursive, which calls each other and refreshes continuously until the alpha value of all particles becomes 0, and the refresh stops.
Public boolean draw (Canvas canvas) { if (!isstarted ()) { return false; } for (particle particle : mparticles) { particle.advance (float) getanimatedvalue ()); if (particle.alpha > 0f) { mpaint.setcolor (Particle.color); mpaint.setalpha ((int) (Color.alpha (Particle.color) * particle.alpha)); canvas.drawcircle (particle.cx, particle.cy, Particle.radius, mpaint); } } mcoNtainer.invalidate (); return true;} 123456789101112131415
Summarize
This open Source Library code quality is very high, very much admire the author.
More Effects ... "It Blue Panther"
Implementation analysis of View burst effect in Android <it Blue Panther >