In the previous article we talked about the custom ripple water ripple effect, first to review the effect it!
After watching the feeling there is no problem, I feel very satisfied at the beginning, then, we take the Android 5.0 comes with the effect to compare
Have you found a different place? Click in the middle of the time is not see what the difference, but click on both sides of the time, it is obvious that our custom effect, ripple to the two sides with the spread of speed, so will appear, if the click is not in the center, the distance from the short side of the ripple first arrived, and the distance from the long side of the arrival, can not The system does not have this situation, so this is an optimization point, another optimization point is: Our custom effect, after the ripple is all covered, the button selection effect is gone.
There are two places that need to be optimized
1, the realization whether or not click the middle point can achieve ripple synchronization to reach the edge
2, when the finger is not released, the selection effect does not disappear
Realize:
The 2nd good realization, we mainly talk about the 1th,
1th We observe the effect of the system, seemingly inconsistent speed caused by the two sides, in fact, we know the implementation of the principle, it is easy to think of, it is constantly changing the circle center to achieve, our last article in the implementation method is a round fixed, is in our finger press position, and constantly change the radius to achieve,
Obviously, it also needs to change the radius to achieve, I remember our last part of the radius of the maximum value is to be calculated, and this effect is not required to calculate, because its maximum value is fixed, is the button diagonal half!
Determines the maximum value of the radius, we also need to determine the center x, y offset, equivalent to the step bar, the center of the button from the pressed point to the middle of the time because it is the radius from 0 to the maximum value of the time consistent, so we can pass the code to get the center of the offset and the maximum radius.
/ * Maximum radius * /Mradius = (float) Math. sqrt(Mrect. Width() /2* Mrect. Width() /2+ Mrect. Height() /2* Mrect. Height() /2);/ * Offset of radius * /Mstepradius = mradius/mcycle;/ * Offset of center X * /Msteporiginx = (mrect. Width() /2-MINITX)/mcycle;/ * Offset of center Y * /Msteporiginy = (mrect. Height() /2-minity)/mcycle;
All implementation Code
PackageEyeclip.myapplication;ImportAndroid.content.Context;ImportAndroid.graphics.Canvas;ImportAndroid.graphics.Paint;ImportAndroid.graphics.Rect;ImportAndroid.support.v4.view.MotionEventCompat;ImportAndroid.support.v4.view.ViewCompat;ImportAndroid.util.AttributeSet;ImportAndroid.view.MotionEvent;ImportAndroid.widget.LinearLayout;/** * Created by Moon.zhong on 2015/4/27. * * Public class ripplelinearlayout extends linearlayout { / * Start point * / Private intMINITX;Private intminity;Private floatMcurrentx;Private floatMcurrenty;/* Height and Width */ Private intMwidth;Private intMheight;/ * radius to draw * / Private floatMradius;Private floatMstepradius;Private floatMsteporiginx;Private floatMsteporiginy;Private floatMdrawradius;Private BooleanMdrawfinish;Private Final intDURATION = Max;Private Final intFREQUENCY =Ten;Private floatMcycle;Private FinalRect Mrect =NewRect ();Private BooleanMpressup =false;PrivatePaint Mrevealpaint =NewPaint (Paint.anti_alias_flag); Public Ripplelinearlayout(Context context) {Super(context); Initview (context); } Public Ripplelinearlayout(context context, AttributeSet attrs) {Super(context, attrs); Initview (context); } Public Ripplelinearlayout(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr); Initview (context); }Private void Initview(Context context) {Mrevealpaint.setcolor (0x25000000); Mcycle = duration/frequency;Final floatDensity = getresources (). Getdisplaymetrics (). density; Mcycle = (density*mcycle); Mdrawfinish =true; }@Override protected void OnDraw(Canvas canvas) {if(Mdrawfinish) {Super. OnDraw (canvas);return; } canvas.drawcolor (0x15000000);Super. OnDraw (canvas);if(Mstepradius = =0) {return; } Mdrawradius = Mdrawradius + Mstepradius; Mcurrentx = Mcurrentx + Msteporiginx; Mcurrenty = Mcurrenty + msteporiginy;if(Mdrawradius > Mradius) {Mdrawradius =0; Canvas.drawcircle (Mrect.width ()/2, Mrect.height ()/2, Mradius, Mrevealpaint); Mdrawfinish =true;if(Mpressup) invalidate ();return; } canvas.drawcircle (Mcurrentx, Mcurrenty, Mdrawradius, Mrevealpaint); Viewcompat.postinvalidateonanimation ( This); }@Override protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {Super. Onmeasure (Widthmeasurespec, Heightmeasurespec); Mrect.set (0,0, Getmeasuredwidth (), Getmeasuredheight ()); }Private void Updatedrawdata() {//int radiuslefttop = (int) math.sqrt ((MRECT.LEFT-MINITX) * (MRECT.LEFT-MINITX) +//(mrect.top-minity) * (mrect.top-minity));//int radiusrighttop = (int) math.sqrt ((MRECT.RIGHT-MINITX) * (MRECT.RIGHT-MINITX) +//(mrect.top-minity) * (mrect.top-minity));//int radiusleftbottom = (int) math.sqrt ((MRECT.LEFT-MINITX) * (MRECT.LEFT-MINITX) +//(mrect.bottom-minity) * (mrect.bottom-minity));//int radiusrightbottom = (int) math.sqrt ((MRECT.RIGHT-MINITX) * (MRECT.RIGHT-MINITX) +//(mrect.bottom-minity) * (mrect.bottom-minity));//Mradius = Getmax (Radiuslefttop, Radiusrighttop, Radiusleftbottom, radiusrightbottom); / * Maximum radius * /Mradius = (float) Math.sqrt (Mrect.width ()/2* Mrect.width ()/2+ mrect.height ()/2* Mrect.height ()/2); ;/ * Offset of radius * /Mstepradius = mradius/mcycle;/ * Offset of center X * /Msteporiginx = (Mrect.width ()/2-MINITX)/mcycle;/ * Offset of center Y * /Msteporiginy = (Mrect.height ()/2-minity)/mcycle; Mcurrentx = MINITX; Mcurrenty = minity; }@Override Public Boolean ontouchevent(Motionevent event) {Final intAction = motioneventcompat.getactionmasked (event);Switch(action) { CaseMotionevent.action_down: {mpressup =false; Mdrawfinish =false;intindex = Motioneventcompat.getactionindex (event);intEventId = Motioneventcompat.getpointerid (event, index);if(EventId! =-1) {MINITX = (int) Motioneventcompat.getx (event, index); Minity = (int) Motioneventcompat.gety (event, index); Updatedrawdata (); Invalidate (); } Break; } CaseMotionevent.action_cancel: CaseMotionEvent.ACTION_UP:mStepRadius = (int) (5* Mstepradius); Msteporiginx = (int) (5* Msteporiginx); Msteporiginy = (int) (5* Msteporiginy); Mpressup =true; Invalidate (); Break; }return Super. Ontouchevent (event); }Private int Getmax(int... radius) {if(Radius.length = =0) {return 0; }intmax = radius[0]; for(intM:radius) {if(M > Max) {max = m; } }returnMax }@Override Public Boolean PerformClick() {postdelayed (NewRunnable () {@Override Public void Run() {ripplelinearlayout.Super. PerformClick (); } }, Max);return true; }}
Contrast
This article is mainly to the content of the previous optimization, of course, you do not think optimization is OK!
Demo download
Android Ripple button Water Ripple effect (ii) optimization