Water-like ripple ball progress bar Controller, Android to achieve high-end atmosphere of the mainstream special effects for everyone to reference, the specific content as follows
Effect Chart:
Circleview
This is mainly the realization of center circle and water wave effect
Package Com.lgl.circleview;
Import Android.content.Context;
Import Android.graphics.Canvas;
Import Android.graphics.Color;
Import Android.graphics.Paint;
Import Android.graphics.Path;
Import Android.graphics.RectF;
Import Android.os.Handler;
Import Android.os.Parcel;
Import android.os.Parcelable;
Import Android.util.AttributeSet;
Import Android.view.View;
Import Android.widget.ProgressBar;
/** * LGL * * * * * * * * * * * */public class Circleview extends View {private context mcontext;
private int mscreenwidth;
private int mscreenheight;
Private Paint Mringpaint;
Private Paint Mcirclepaint;
Private Paint Mwavepaint;
Private Paint Linepaint;
Private Paint Flowpaint;
Private Paint Leftpaint;
private int mringstrokewidth = 15;
private int mcirclestrokewidth = 2;
private int mlinestrokewidth = 1;
private int mcirclecolor = Color.White;
private int mringcolor = Color.White;
private int mwavecolor = Color.White;
Private Handler Mhandler;
Private long C = 0L; PRivate Boolean mstarted = false;
Private final float f = 0.033F; private int malpha = 50;//transparency private float mamplitude = 10.0F;
Amplitude private float Mwaterlevel = 0.5f;//Water High (0~1) private Path mpath;
The drawing text is shown in the middle of the circle, but I do not set it, I think the layout is also very good private String flownum = "";
Private String Flowleft = "still remaining";
/** * @param context */public Circleview (context) {super (context);
TODO auto-generated constructor stub mcontext = context;
Init (Mcontext); /** * @param context * @param attrs/Public Circleview (context, AttributeSet attrs) {Super
, attrs);
TODO auto-generated constructor stub mcontext = context;
Init (Mcontext); /** * @param context * @param attrs * @param defstyleattr/Public Circleview (context, AttributeSet
attrs, int defstyleattr) {Super (context, attrs, defstyleattr);
TODO auto-generated constructor stub mcontext = context;
Init (Mcontext); } public void Setmwaterlevel (float mWaterlevel) {this.mwaterlevel = Mwaterlevel;
private void init (context context) {Mringpaint = new Paint ();
Mringpaint.setcolor (Mringcolor);
Mringpaint.setalpha (50);
Mringpaint.setstyle (Paint.Style.STROKE);
Mringpaint.setantialias (TRUE);
Mringpaint.setstrokewidth (Mringstrokewidth);
Mcirclepaint = new Paint ();
Mcirclepaint.setcolor (Mcirclecolor);
Mcirclepaint.setstyle (Paint.Style.STROKE);
Mcirclepaint.setantialias (TRUE);
Mcirclepaint.setstrokewidth (Mcirclestrokewidth);
Linepaint = new Paint ();
Linepaint.setcolor (Mcirclecolor);
Linepaint.setstyle (Paint.Style.STROKE);
Linepaint.setantialias (TRUE);
Linepaint.setstrokewidth (Mlinestrokewidth);
Flowpaint = new Paint ();
Flowpaint.setcolor (Mcirclecolor);
Flowpaint.setstyle (Paint.Style.FILL);
Flowpaint.setantialias (TRUE);
Flowpaint.settextsize (36);
Leftpaint = new Paint ();
Leftpaint.setcolor (Mcirclecolor);
Leftpaint.setstyle (Paint.Style.FILL);
Leftpaint.setantialias (TRUE); Leftpaint. Settextsize (36);
Mwavepaint = new Paint ();
Mwavepaint.setstrokewidth (1.0F);
Mwavepaint.setcolor (Mwavecolor);
Mwavepaint.setalpha (Malpha);
MPath = new Path ();
Mhandler = new Handler () {@Override public void Handlemessage (Android.os.Message msg) {if (Msg.what = 0) {
Invalidate ();
if (mstarted) {///keep sending messages to yourself, so that you are constantly redrawn mhandler.sendemptymessagedelayed (0, 60L);
}
}
}
}; @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {int width = measure (widthmeasures
PEC, true);
int height = measure (Heightmeasurespec, false);
if (width < height) {setmeasureddimension (width, width);
else {setmeasureddimension (height, height); /** * @category Measurement * @param measurespec * @param iswidth * @return/private int measure (int measuresp
EC, Boolean iswidth) {int result;
int mode = Measurespec.getmode (MEASURESPEC);
int size = Measurespec.getsize (MEASURESPEC); int Padding = Iswidth?
Getpaddingleft () + getpaddingright (): Getpaddingtop () + Getpaddingbottom ();
if (mode = = measurespec.exactly) {result = size;
else {result = Iswidth getsuggestedminimumwidth (): Getsuggestedminimumheight ();
result = padding;
if (mode = = Measurespec.at_most) {if (iswidth) {result = Math.max (result, size);
else {result = Math.min (result, size);
}} return result; @Override protected void onsizechanged (int w, int h, int oldw, int oldh) {//TODO auto-generated method stub sup
Er.onsizechanged (W, H, OLDW, OLDH);
Mscreenwidth = W;
Mscreenheight = h;
@Override protected void OnDraw (Canvas Canvas) {//TODO auto-generated Method Stub Super.ondraw (Canvas);
Gets the control's width high int width = getwidth ();
int height = getheight ();
SetBackgroundColor (Mcontext.getresources (). GetColor (R.COLOR.MAIN_BG)); Calculates the distance between the current line of oil and the horizontal midline float Centeroffset = Math.Abs (MSCREENWIDTH/2 * mwaterlevel-mscreenWIDTH/4);
Calculates the oil line and the angle with the horizontal midline float Horiangle = (float) (Math.asin (Centeroffset/(MSCREENWIDTH/4)) * 180/math.pi);
Fan-shaped starting angle and sweeping angle float startangle, sweepangle;
if (Mwaterlevel > 0.5F) {startangle = 360f-horiangle;
Sweepangle = 180F + 2 * horiangle;
else {startangle = Horiangle;
Sweepangle = 180f-2 * Horiangle; Canvas.drawline (Mscreenwidth * 3/8, Mscreenheight * 5/8, Mscreenwidth * 5/8, Mscreenheight * 5/8, LinePai
NT);
float num = flowpaint.measuretext (flownum);
Canvas.drawtext (Flownum, Mscreenwidth * 4/8-NUM/2, Mscreenheight * 4/8, Flowpaint);
float left = Leftpaint.measuretext (Flowleft);
Canvas.drawtext (Flowleft, Mscreenwidth * 4/8-LEFT/2, Mscreenheight * 3/8, Leftpaint); If not started (Startwave method is not invoked), draw a fan if (!mstarted) | | (mscreenwidth = 0) | | (mscreenheight = 0)) {//Draw, that is, the height of the water surface at rest rectf oval = new RECTF (MSCREENWIDTH/4, MSCREENHEIGHT/4, Mscreenwidth * 3/4, Mscreenheig Ht * 3/4);
Canvas.drawarc (oval, StartAngle, Sweepangle, False, Mwavepaint);
Return //drawing, that is, the height//drawing of the water surface at rest, that is, the height of the water surface at rest rectf oval = new RECTF (MSCREENWIDTH/4, MSCREENHEIGHT/4, Mscreenwidth * 3/
4, Mscreenheight * 3/4);
Canvas.drawarc (oval, StartAngle, Sweepangle, False, Mwavepaint);
if (this.c >= 8388607L) {this.c = 0L;
c = (1L + c) Each time the OnDraw is added;
FLOAT F1 = mscreenheight * (1.0F-(0.25F + MWATERLEVEL/2))-mamplitude;
The length of the current line of oil is float wavewidth = (float) math.sqrt (mscreenwidth * mscreenwidth/16-centeroffset * centeroffset);
Offset from the radius of the circle float offsetwidth = MSCREENWIDTH/4-wavewidth;
int top = (int) (F1 + mamplitude);
Mpath.reset ();
Start vibration x coordinate, end vibration x coordinate int startx, endx;
if (Mwaterlevel > 0.50F) {startx = (int) (MSCREENWIDTH/4 + offsetwidth);
EndX = (int) (MSCREENWIDTH/2 + MSCREENWIDTH/4-offsetwidth);
else {startx = (int) (MSCREENWIDTH/4 + offsetwidth-mamplitude); EndX = (int)
(MSCREENWIDTH/2 + MSCREENWIDTH/4-offsetwidth + mamplitude); }//Wave effect while (StartX < endx) {int starty = (int) (F1-mamplitude * Math.sin (Math.PI * (2.0F * (
StartX + this.c * Width * this.f)) (width));
Canvas.drawline (StartX, Starty, StartX, Top, mwavepaint);
startx++;
} canvas.drawcircle (MSCREENWIDTH/2, MSCREENHEIGHT/2, MSCREENWIDTH/4 + MRINGSTROKEWIDTH/2, mRingPaint);
Canvas.drawcircle (MSCREENWIDTH/2, MSCREENHEIGHT/2, MSCREENWIDTH/4, Mcirclepaint);
Canvas.restore ();
@Override public parcelable onsaveinstancestate () {parcelable superstate = super.onsaveinstancestate ();
savedstate ss = new savedstate (superstate);
ss.progress = (int) c;
return SS;
@Override public void Onrestoreinstancestate (parcelable state) {savedstate SS = (savedstate) state;
Super.onrestoreinstancestate (Ss.getsuperstate ());
c = ss.progress; } @Override protected void Onattachedtowindow () {Super.onaTtachedtowindow ();
Turn off hardware acceleration to prevent abnormal unsupported operation exception This.setlayertype (view.layer_type_software, NULL);
} @Override protected void Ondetachedfromwindow () {Super.ondetachedfromwindow ();
/** * @category Start fluctuation * * public void Startwave () {if (!mstarted) {this.c = 0L;
Mstarted = true;
This.mHandler.sendEmptyMessage (0);
}/** * @category stop fluctuation */public void Stopwave () {if (mstarted) {this.c = 0L;
mstarted = false;
This.mHandler.removeMessages (0);
}/** * @category save state */Static class Savedstate extends Basesavedstate {int progress;
/** * constructor called from {@link progressbar#onsaveinstancestate ()} */savedstate (parcelable superstate) {
Super (superstate);
}/** * constructor called from {@link #CREATOR} */Private savedstate (Parcel in) {super (in);
progress = In.readint (); @Override public void Writetoparcel (Parcel out, int flags) {Super.writetoparcel (out, Flags);
Out.writeint (progress); public static final parcelable.creator<savedstate> Creator = new parcelable.creator<savedstate> () {PU
Blic savedstate Createfromparcel (Parcel in) {Return to New savedstate (in);
Savedstate[] NewArray (int size) {return new savedstate[size];
}
};
}
}
Let's run a little bit.
In fact, he is very empty, so it is worth us to customize, we add a flow in the middle of the show, and then add a progress bar
Activity_main.xml
<?xml version= "1.0" encoding= "Utf-8"?> <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" android:background= "@color/main_bg" > <textview android:layout_width= "wrap_content" android:l ayout_height= "Wrap_content" android:layout_alignparenttop= "true" Android:layout_centerhorizontal= "true" Android: layout_margintop= "10DP" android:text= "Traffic" android:textcolor= "@android: Color/white" android:textsize= "18sp"/> & Lt;com.lgl.circleview.circleview android:id= "@+id/wave_view" android:layout_width= "Fill_parent" Android:layout_ height= "Fill_parent" android:layout_centerinparent= "true"/> <textview android:id= "@+id/power" android:layou T_width= "Wrap_content" android:layout_height= "Wrap_content" android:layout_centerinparent= "true" Android: Textcolor= "@android: Color/white"/> <seekbar anDroid:id= "@+id/seekbar" android:layout_width= "match_parent" android:layout_height= "Wrap_content" Android:layout_
Alignparentbottom= "true" android:layout_marginbottom= "150DP"/> </RelativeLayout>
To implement this, we need to invoke its initialization and the Start method.
Mcircleview = (Circleview) Findviewbyid (R.id.wave_view);
Set how high, float,0.1-1f
mcircleview.setmwaterlevel (0.1F);
Start execution of
mcircleview.startwave ();
Don't forget to recycle it when the activity is destroyed.
@Override
protected void OnDestroy () {
//TODO auto-generated method stub
Mcircleview.stopwave ();
Mcircleview = null;
Super.ondestroy ();
}
Let's run it again.
But how do we get the water ripple up and down along with the progress bar, Johnny? , here we're going to use the seekbar we just wrote, and we've achieved it.
Setonseekbarchangelistener to monitor, so we're going to make a copy of his three methods, where we just use a public
void onprogresschanged (SeekBar SeekBar, int Progress,
Boolean fromuser) {
//Follow progress bar scrolling
mcircleview.setmwaterlevel ((float) progress/100);
}
Here, we're going to do this, we set the height of the unit is float, that is, from the 0-1f, and our progress is int progress, from 0-100, we have to use (float) progress/100) and strong transfer to get the unit, OK, The height of our water ripple is changing with our progress bar, let's run it again.
Well, in that case, there's only one left. is to let the size change with our progress bar, where we can not operate in the main thread because of the update UI, so we need to use our old buddy handler, but it's not enough to use the handler, and our progress bar values are in the inner class, So here we need to use the handler to pass the value, here we use the bundle, we still operate in the Onprogresschanged method
Creates a message messages
= new ();
Bundle Bundle = new Bundle ();
put an int value
Bundle.putint ("Progress", progress);
Load
message.setdata (bundle);
Send messages
handler.sendmessage (message);
Create expression
message.what = 1;
The message was sent, and we wrote a handler in front of it to receive it.
Private Handler Handler = new Handler () {public
void Handlemessage (Android.os.Message msg) {
if (msg.what = 1) {
int num = Msg.getdata (). GetInt ("Progress");
LOG.I ("num", num + "");
Power.settext ((float) num/100 * max + "m/" + Max + "M");}}
;
Here's the formula for the Gini, which is the current value/100 gets a percentage to go * maximum. We can now complete the run, in fact, and the top running picture is the same
Mainactivity
Package Com.lgl.circleview;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.os.Handler;
Import Android.os.Message;
Import Android.util.Log;
Import Android.widget.SeekBar;
Import Android.widget.TextView;
public class Mainactivity extends activity {private Circleview Mcircleview;
Private SeekBar Mseekbar;
Private TextView power;
private int max = 1024;
private int min = 102; Private Handler Handler = new Handler () {public void Handlemessage (Android.os.Message msg) {if (Msg.what = 1) {in
T num = Msg.getdata (). GetInt ("Progress");
LOG.I ("num", num + "");
Power.settext ((float) num/100 * max + "m/" + Max + "M");
}
}
};
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Getactionbar (). Hide ();
Setcontentview (R.layout.activity_main);
Power = (TextView) Findviewbyid (r.id.power);
Power.settext (min + "m/" + Max + "M");
Mcircleview = (Circleview) Findviewbyid (R.id.wave_view); Set how high, float, 0.1-1f Mcircleview.setmwaterlevel (0.1F);
Start execution of Mcircleview.startwave ();
Mseekbar = (SeekBar) Findviewbyid (R.id.seekbar); Mseekbar.setonseekbarchangelistener (New Seekbar.onseekbarchangelistener () {@Override public void onprogresschanged (
SeekBar SeekBar, int progress, Boolean fromuser) {Mcircleview.setmwaterlevel ((float) progress/100);
Creates a message messages = new ();
Bundle Bundle = new Bundle ();
put an int value bundle.putint ("Progress", progress);
Load Message.setdata (bundle);
Send messages Handler.sendmessage (message);
Create expression message.what = 1; @Override public void Onstarttrackingtouch (SeekBar SeekBar) {} @Override public void Onstoptrackingtouch (S
Eekbar seekBar) {}});
@Override protected void OnDestroy () {//TODO auto-generated Method Stub mcircleview.stopwave ();
Mcircleview = null;
Super.ondestroy ();
}
}
Code Download:Android Simulated water ripple Flow ball progress bar
This is the entire content of this article, I hope to learn more about Android software programming help.