The first two days saw the imitation of the effect of the water ripple in the Android L two blog
The realization of the click effect of water ripple in Android l
Android Custom Component Series "14"--android5.0 button ripple effect implementation
The first one is to implement a water ripple layout, where all the controls on the inside will have a ripple effect when clicked
The second is the realization of a water ripple view, after clicking on itself will appear ripple effect
According to the understanding of the two blog, I realized a similar thing, did not find the right screen software, had to speed up the ripple of a lot to record down, can see what the meaning, not adjust the speed of the words are more elegant.
It is a control like the one above, the background is a rewrite of the TextView, the background has been a constant "breathing" bubbles.
Here is the first two blog (recommended to go to see), introduced under the view and ViewGroup to achieve background animation, while recording their understanding of the inside knowledge points.
Temporarily name the effect as a breathing bubble. (later found that this figure does not move, well, I do not know why not waste time, I imagined this whole background has a circle, constantly zoom in and zoom out, center random, this is just random to the upper left corner position)
First, ViewGroup.
This is a direct example of the first blog, the record of their own understanding
1. Get the coordinates, this is an important step, and then judge the click of the control and draw the ripple need to use
@Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {super.onlayout (changed, L, T, R, b); this.ge Tlocationonscreen (Mlocationinscreen);}
This gets the coordinates of the top left corner of the current layout in the entire screen
2. Get the clicked control, here the acquisition needs to be judged according to the coordinates, in the Dispatchtouchevent method will pass in the current click event Motionevent, he will bring into the current click of the coordinates, there are two ways to obtain, one is Getx, One is getrawx, in the view of the coordinate system to say the difference between the two, in order to calculate the click event, here to get the relative screen coordinates, in fact, in the layout of the rewrite inside the entire piece is used relative to the screen coordinates, because the layout will appear nested, the relative coordinates after nesting is not right, So all use relative screen coordinates to calculate. To get the coordinates of the click event, you can take the coordinates to find the control you clicked. The whole process blog is already very detailed.
3. After you have clicked on the control to draw a ripple on the control, where the code is pasted
View Drawing process: Draw the background first, then draw yourself (OnDraw), then draw the child elements (Dispatchdraw), and finally draw some decorations such as scrollbars (ondrawscrollbars)//In order to prevent the drawing of sub-elements to block the ripples, Here choose to draw the ripple @overrideprotected void Dispatchdraw (canvas canvas) {Super.dispatchdraw (canvas) in the child element drawing done again; mshoulddoanimation | | Mtargetwidth < 0 | | Mtouchtarget = = null) {return;} if (Mrevealradius > MMINBETWEENWIDTHANDHEIGHT/2) {//When the radius exceeds the short edge, increase the diffusion speed to complete the diffusion as soon as possible Mrevealradius + = Mrevealradiusgap * 4;} el SE {//ripple when RADIUS increases diffusion Mrevealradius + = Mrevealradiusgap;} This.getlocationonscreen (Mlocationinscreen);//Get the coordinates of this layout---1?? int[] location = new Int[2];mtouchtarget.getlocationonscreen;//Get the coordinates of the click Control---2?? int left = location[0]-mlocationinscreen[0];//---3?? int top = location[1]-Mlocationinscreen[1];int right = left + mtouchtarget.getmeasuredwidth (); int bottom = top + Mtoucht Arget.getmeasuredheight (); Canvas.save () Canvas.cliprect (left, top, right, bottom);//---4?? Canvas.drawcircle (Mcenterx, Mcentery, Mrevealradius, Mpaint); Canvas.restore (); if (Mrevealradius <= Mmaxrevealradius) {PostiNvalidatedelayed (Invalidate_duration, left, top, right, bottom);//---5??} else if (!mispressed) {mshoulddoanimation = false;postinvalidatedelayed (Invalidate_duration, left, top, right, bottom);}}
The entire drawing process is the above, or focus on the calculation of the cutting and coordinate of the canvas, drawing process and the calculation of the radius and so on to see.
1?? Gets the coordinates of the upper-left corner of the layout
2?? Gets the coordinates of the upper-left corner of the control
3?? The coordinates of the control, minus the coordinates of the layout, are the relative coordinates of the layout on the control, where the relative coordinates are actually the concepts of getleft and gettop, but not so, because it is possible that there are nested layouts between the control and the layout
4?? At 3?? The coordinates of the control relative to the layout have been obtained, where the control's position is cut down on the layout canvas, and then rounded and cut to improve performance
5?? Here after the completion of the circle to draw a larger radius of the circle, so as to achieve the spread of the effect, so to postinvalidatedelayed to refresh, refresh only refresh the corresponding area of the control, but also to improve performance
Basically this, the original Bo has been more detailed, I am only for their own understanding of the record.
And then the view.
Take a look at a couple of steps
1. Gets the width and height information of the current control (information that is used to initialize the radius of the bubble)
2. Get the Click event (used as the center of the bubble, it is a random coordinate when there is no click event, and click to move to the location of the click)
3. Draw Bubbles
The following is the rewritten Breathtextview code
public class Jasonbreathtextview extends TextView {private jasonbreathcircle breathcircle;public Jasonbreathtextview ( Context context) {super (context);} Public Jasonbreathtextview (context context, AttributeSet Attrs) {Super (context, attrs); breathcircle = new Jasonbreathcircle (context);} @Overrideprotected void onsizechanged (int w, int h, int oldw, int oldh) {//TODO auto-generated method Stubsuper.onsizecha Nged (W, H, OLDW, OLDH); Breathcircle.initparameters (this);} @Overridepublic boolean ontouchevent (Motionevent event) {breathcircle.setcirclecenter ((int) event.getx (), (int) Event.gety ()); return super.ontouchevent (event);} @Overrideprotected void OnDraw (canvas canvas) {breathcircle.draw (canvas); Super.ondraw (canvas);} /** * Start watermark effect */public void Startreveal () {Breathcircle.start ();} /** * Stop the watermark effect */public void Stopreveal () {breathcircle.stop ();}}
This is the control that inherits from TextView used in the diagram.
For ease of use, I separated the implementation of the bubbles from the implementation of the control, so that regardless of which view you implement, you can use the separated bubble class directly, using the method as above, just pass the view control itself to the bubble, and the bubbles will be drawn on the control.
The code for the Bubble breathcircle is as follows:
public class Jasonbreathcircle {private static int diffuse_gap = 2;//diffusion radius increment private static final int invalidate_duration = 10; interval for each refresh private Context mcontext;private boolean needtodrawreveal = false;//painting flag bit//Some properties of the circle itself private Boolean islarge Rmode = true;//Breathing mode private Paint mpaintreveal;//brush private int mcirclecenterx;//Center xprivate int mcirclecentery;//Center Ypriv ate int mcurradius;//the current radius private int mmaxradius;//maximum radius//Some properties of the attached control, using the height width to calculate the position of the current touch point private View mparentview;// Dependency control private int mparentheight;//control height private int mparentwidth;//control width//================ initialization method (must be called) ===============/* * * Instantiate a circle, then call Initparameters to initialize the properties of the circle, then draw the * * @param context */public jasonbreathcircle (context context) {Mcont ext = Context;initpaint ();} /** * Incoming view, used to initialize coordinates, RADIUS, by default start with center circle * * @param view */public void initparameters (view view) {This.mparentview = view;// Gets the property of the current dependent control Mparentheight = Mparentview.getheight (); mparentwidth = Mparentview.getwidth ();//Initialize the Circle property Mmaxradius = (int) Math.hypot(View.getheight (), View.getwidth ())/2;//The width height of the control to find the initial center Mcirclecenterx = Mparentwidth/2;mcirclecentery = Mparentheight /2;} /** * Incoming Canvas * * @param canvas */public void draw (canvas canvas) {if (needtodrawreveal) {canvas.save (); Canvas.drawcircle (MC Irclecenterx, Mcirclecentery, mcurradius,mpaintreveal); Canvas.restore (); if (Islargermode && MCurRadius < Mmaxradius) {Mcurradius + = diffuse_gap;//Ripple increment postrevealinvalidate ();} else if (Mcurradius > 0 &&!islargermod e) {//finish drawing a cycle from scratch mcurradius-= diffuse_gap;//ripple increment postrevealinvalidate ();} else {//conversion Mode Islargermode =!islargermode;//with The machine chooses coordinates as the center, takes x from 0 to the right, and takes ysetcirclecenter from 0 to the bottom (jasonrandomutil.nextint (0, Mparentwidth), Jasonrandomutil.nextint (0, Mparentheight));//center change, before shrinking, the current radius is set to maximum, to prevent white space on the side of the cover is not satisfied if (!islargermode) {Mcurradius = Mmaxradius;} Postrevealinvalidate ();}}} =============== external Interface ===============/** * Start breathing */public void start () {if (needtodrawreveal) {return;} Needtodrawreveal = True;postrevealinvalidate ();} /** * Stop Breathing */public void Stop () {if (!needtodrawreveal) {return;} Needtodrawreveal = False;reset ();p ostrevealinvalidate ();} /** * Set Center Circle * * @param x * @param y */public void setcirclecenter (int x, int y) {Mcirclecenterx = X;mcirclecentery = Y;mma Xradius = Jasonradiusutil.getmaxradius (Mcirclecenterx,mcirclecentery, Mparentwidth, mParentHeight);} /** * Sets whether the circle is hollow or solid, the default solid * * @param ishollow */public void Sethollow (Boolean ishollow) {Mpaintreveal.setstyle (ishollow? Paint.Style.STROKE:Paint.Style.FILL);} ================ Internal Implementation ===============/** * Reset */private void Reset () {Mcurradius = 0;islargermode = true;} /** * Initialize brush */private void Initpaint () {mpaintreveal = new Paint (); Mpaintreveal.setcolor (Mcontext.getresources (). GetColor (R.color.jason_bg_common_green_light)); Mpaintreveal.setantialias (true);} /** * Redraw */private void Postrevealinvalidate () {mparentview.postinvalidatedelayed (invalidate_duration);}}
Get the width and height information of the control is in onsizechanged this method, there will be a wide high information to get
Get the Click event is inside the Ontouchevent
The last draw here chooses the OnDraw method
If you've seen the first two blogs, there are two places to be recorded:
1?? In fact, there are several ways to draw a look at the view drawing process: Draw the background first, then draw your own (OnDraw), then draw the child elements (Dispatchdraw), and finally draw some decorations such as scroll bar (ondrawscrollbars)
Because this is to draw out the bubbles to do the background, so to draw the bubble in the completion of the view itself to draw some things, so in the OnDraw is the most suitable
2?? About coordinates, due to the first blog in the previous layout rewrite the effect of the coordinate processing, here wasted some time, in fact, in the view of the rewrite, the use of coordinates when redrawing, just need to know the width of the view is enough, because the OnDraw passed in the canvas is the size of the control itself,
So you don't need to crop the canvas as you would in the layout, just draw it directly on it. coordinate system directly according to the width of the height to establish the line, the upper left corner is the origin point.
jason0539
Weibo: http://weibo.com/2553717707
Blog: http://blog.csdn.net/jason0539 (reprint please indicate the source)
Android View and LinearLayout rewrite (for background bubbles and ripple effects)