Ordinary buttons are so several styles, looking at all aesthetic fatigue, first put the effect chart:
Do you think this button is assembled with a lot of animation products, I tell you, and No. All implementations are based on Custom view, using the lowest-OnDraw 1.1-point drawing. Did not use a slightest animation. Although the demo time is very short, but to complete so many changes, still very laborious.
First, explain the usage:
public class Mainactivity extends activity {@Override protected void onCreate (Bundle savedinstancestate) {SUPER.ONCR
Eate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Final Animationbutton button = (Animationbutton) Findviewbyid (R.id.button); Button.settextsizetouch (25); Sets the font size when pressed, without setting a default value//Button.setstrokeprogress (10); Set the thickness of the progress bar, do not set a default value//Button.setcolorbase (Color.green); Sets the overall base color without setting a default value//Button.setcolorback (Color.gray); Set the background color of the progress bar, do not set a default value//Button.setstroke (3); Set the thickness of the border without setting a default value//Button.setstroketext (0); Sets the thickness of the text without setting a default value//Button.settextsize (30); Sets the font size of the text without setting a default value//Button.setround (30); Set rounded corners without setting a default value of Button.settext ("login"); Sets the text without setting a default value of Button.setmode (AnimationButton.Mode.Hand_Finish); Set the progress bar mode without setting a default value Mode.auto_finish Button.setonanimationbuttonclicklistener (new Animationbutton.onanimationbuttonclicklistener () {@Override public void OnClick () {//stopprogress method is only Button.setm
Ode (AnimationButton.Mode.Hand_Finish); button. stopprogress ();
}
});
}
}
In fact, if only the most common function, there is nothing to do. Because almost all of the parameters have been set in a fixed setting. The function usage that is commented on above is also the only few functions that the user can use, while the other functions are marked public, but they are passed by the method within the component instead of being invoked by the outside user. So if you want to customize the style, you can call the method in the annotation.
The following start source explanation, first decomposition function, all changes can be divided into three states:
1, the default state, which is the initial state. The main thing to do is: Receive user clicks, change the background style from hollow to solid, dynamically change the size of the text, and then gradually narrowing into a circle.
2, progress bar status. The main completion of the progress bar of the progression, the demonstration on the map only a round. In fact, you can set a parameter, rotate many laps until the user manually stop, or even infinite rotation
3, end state. It mainly completes the state of the rounded rectangle by the state of the circle and renders the logo in the middle.
Since the split out of the state, then use the state machine + proxy mode to achieve this function bar. The first is the enumeration of States.
/**
* Created by CCWXF on 2016/2/29.
* For the difference status, there are: Default state, progress bar status, end state/public
enum status {
default,
Progress,
finish
}
Then there is the interface of the state machine, which is the common thing that all States need to accomplish:
/**
* Created by CCWXF on 2016/2/29.
* * Public
interface Buttonstatus {
/**
* * @return corresponding status value *
/Status GetStatus ();
/**
* The event handling agent for this state *
@param mevent
*
@return
/boolean ontouchevent (Motionevent mevent);
/**
* This state of the rendering agent
* @param mcanvas
* @param
mpaint
/void OnDraw (Canvas mcanvas, Paint mpaint);
}
Then we implement the button's code, which is the custom view:
/** * Created by CCWXF on 2016/2/29.
* * public class Animationbutton extends View {private static int color_base = Color.rgb (24, 204, 149);
private static int color_back = COLOR.RGB (153, 153, 153);
private static int Stroke = 3;
private static int stroke_text = 0;
private static int stroke_progress = 10;
private static int text_size = 30;
private static int text_size_touch = 25;
private static int Round = 30;
private static String Text = "Submit";
Private Mode mode = Mode.auto_finish;
private int maxwidth;
private int maxheight;
private int colorbase = Color_base;
private int colorback = Color_back;
private int stroke = stroke;
private int stroketext = Stroke_text;
private int strokeprogress = stroke_progress;
private int textsize = Text_size;
private int textsizetouch = Text_size_touch;
private int round = round;
Private String text = text;
Whether to stop the progress bar, the outside set private Boolean isprogressstop = false;
Private Paint Mpaint = new Paint (Paint.anti_alias_flag); PrivaTe buttonstatus status;
Private Onanimationbuttonclicklistener listener;
Public Mode GetMode () {return mode;
public void SetMode (mode mode) {This.mode = mode;
public int getmaxwidth () {return maxwidth;
public int getmaxheight () {return maxheight;
public int Gettextsizetouch () {return textsizetouch;
The public void Settextsizetouch (int textsizetouch) {This.textsizetouch = Textsizetouch;
public int getstrokeprogress () {return strokeprogress;
The public void setstrokeprogress (int strokeprogress) {this.strokeprogress = strokeprogress;
public int getcolorbase () {return colorbase;
The public void setcolorbase (int colorbase) {this.colorbase = Colorbase;
public int Getcolorback () {return colorback;
The public void setcolorback (int colorback) {this.colorback = Colorback;
public int Getstroke () {return stroke;
The public void Setstroke (int stroke) {This.stroke = stroke; public int Getstroketext () {return StroketexT
The public void Setstroketext (int stroketext) {this.stroketext = Stroketext;
public int gettextsize () {return textsize;
The public void settextsize (int textsize) {this.textsize = Textsize;
public int Getround () {return round;
The public void Setround (int round) {this.round = round;
Public String GetText () {return text;
public void SetText (String text) {this.text = text;
Public Animationbutton {Super (context);
Public Animationbutton (context, AttributeSet attrs) {Super (context, attrs);
Public Animationbutton (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); @Override public boolean ontouchevent (Motionevent event) {if (status!= null) {return Status.ontouchevent (event
);
Return Super.ontouchevent (event);
} @Override protected void OnDraw (Canvas Canvas) {if (status!= null) {Status.ondraw (Canvas, mpaint); }} @Override protected void Onmeasure (int widthmeasurespec, int heightmeasurespec) {maxwidth = Measurespec.getsize (Widthmeasurespec);
MaxHeight = Measurespec.getsize (Heightmeasurespec);
if (maxwidth!= 0 && maxheight!= 0) {status = new Defaultstatus (this, maxwidth, maxheight);
} super.onmeasure (Widthmeasurespec, Heightmeasurespec); /** * Change the overall state * * @param s changed state * @param width current widths * @param height current heights/public void Changestatus (status s
, int width, int height, int centerx, int centery) {switch (s) {case default:break;
Case Progress://Change state, enter progress bar status = New Progressstatus (this, width, height, centerx, centery);
Invalidate ();
Break
Case Finish://Enter the end status status = New Finishstatus (this, width, height, centerx, centery);
Invalidate ();
Break
}/** * Outside set stop progress bar/public void stopprogress () {this.isprogressstop = true;
/** * Check whether the progress bar ends * @return * * * public boolean isprogressstop () {return isprogressstop; } public enum mode{Auto_finISH, hand_finish} public interface onanimationbuttonclicklistener{void OnClick ();
public void Setonanimationbuttonclicklistener (Onanimationbuttonclicklistener listener) {This.listener = listener;
Public Onanimationbuttonclicklistener Getonanimationbuttonclicklistener () {return listener;
}
}
The above implementation of a bunch of variable parameters for user customization. Then, in the Ontouchevent and OnDraw methods, all the actions are represented.
Then we'll implement the first state, which is the default state:
/** * Created by CCWXF on 2016/2/29. * * Public class Defaultstatus implements Buttonstatus {//= Four child states that are in default state private static final int status_default = 0
;
private static final int status_touch = 1;
private static final int status_up = 2;
private static final int status_next = 3;
Gradient and time spacing when the width is refreshed private static final int delay_next = 500;
private static final int delay_frush = 10;
private static final int pixel_frush = 8;
Button object private Animationbutton button;
The length and midpoint coordinates of the button object (long width is the length of the drawing, not the width of the control) private int width;
private int height;
private int CenterX;
private int centery;
Child state variable private int status = Status_default;
Private Handler Handler = new Handler ();
Public defaultstatus (Animationbutton button, int width, int height) {This.button = button;
This.width = width;
This.height = height;
This.centerx = WIDTH/2;
This.centery = HEIGHT/2;
@Override public Status GetStatus () {return status.default; @Override public Boolean Ontouchevent(Motionevent mevent) {switch (mevent.getaction ()) {case Motionevent.action_down://When pressed, toggle to status if (status = = Status_default) {Statu
s = Status_touch;
Button.invalidate ();
return true; Case MotionEvent.ACTION_UP:case Motionevent.action_cancel://lift, or remove control, switch to lift driver status if (status = = Status_touch) {St
ATUs = status_up;
Button.invalidate (); Scaling changes begin after 500ms delay handler.postdelayed (new Runnable () {@Override public void run () {//Toggle to Next Child State if (St
ATUs = = status_up) {Status = Status_next;
} if (status = = Status_next) {//If the width is inconsistent, continue the gradient, otherwise change the state if (width >= height) {width = Pixel_frush;
Button.invalidate ();
Handler.postdelayed (this, delay_frush);
}else{button.changestatus (status.progress, width, height, centerx, centery);
}}}, Delay_next);
Response Listener Animationbutton.onanimationbuttonclicklistener listener = Button.getonanimationbuttonclicklistener (); if (listener!= null) {LIstener.onclick ();
}} break;
return false; @Override public void OnDraw (Canvas mcanvas, Paint mpaint) {switch (status) {case Status_default:ondrawdefaul
T (Mcanvas, Mpaint);
Break
Case Status_touch:ondrawtouch (Mcanvas, mpaint);
Break
Case Status_up:ondrawup (Mcanvas, mpaint);
Break
Case Status_next:ondrawnext (Mcanvas, mpaint);
Break
}/** * Draw border, divided into hollow and solid two * * @param mcanvas Canvas * @param mpaint brush * @param style hollow or solid * @param padding Border filler * * private void Drawround (Canvas mcanvas, Paint mpaint, paint.style Style, int padding) {Mpaint.setcolor (Button.getcolorb
ASE ());
int stroke = padding;
if (style = = Paint.Style.STROKE) {mpaint.setstyle (Paint.Style.STROKE);
Mpaint.setstrokewidth (Button.getstroke ());
Stroke + + Button.getstroke ()/2;
else {mpaint.setstyle (Paint.Style.FILL); //Draw Border Mcanvas.drawroundrect (new RECTF (Stroke, stroke, width-stroke, Height-stroke), Button.getround (), Button.get Round (), MpaiNT); /** * Painting text, there is the difference between font size and color * * @param mcanvas Canvas * @param mpaint brush * @param textsize Font size * @param textcolor Font Color *
/private void DrawText (Canvas mcanvas, Paint mpaint, int textsize, int textcolor) {mpaint.setcolor (textcolor);
Mpaint.setstrokewidth (Button.getstroketext ());
Mpaint.settextsize (TEXTSIZE);
Paint.fontmetrics metrics = Mpaint.getfontmetrics ();
int textWidth = (int) mpaint.measuretext (Button.gettext ());
int baseLine = (int) (HEIGHT/2 + (metrics.bottom-metrics.top)/2-metrics.bottom);
Mcanvas.drawtext (Button.gettext (), (width-textwidth)/2, BaseLine, mpaint);
/** * Draw the default state button * * @param mcanvas * @param mpaint/private void Ondrawdefault (Canvas mcanvas, Paint mpaint) {
Drawround (Mcanvas, Mpaint, Paint.Style.STROKE, 0);
Draw Centered text DrawText (Mcanvas, Mpaint, Button.gettextsize (), button.getcolorbase ());
/** * Draws the pressed state button * * @param mcanvas * @param mpaint/private void Ondrawtouch (Canvas mcanvas, Paint mpaint) { Drawround (MCanvas, Mpaint, Paint.Style.FILL, Button.getstroke ());
Draw text, font to change DrawText (Mcanvas, Mpaint, Button.gettextsizetouch (), color.white); /** * Draw the lift State button * * @param mcanvas * @param mpaint * * private void Ondrawup (Canvas mcanvas, Paint mpaint) {DRA
Wround (Mcanvas, Mpaint, Paint.Style.FILL, 0);
DrawText (Mcanvas, Mpaint, Button.gettextsize (), color.white);
/** * Draws the button to the next state * * @param mcanvas * @param mpaint/private void Ondrawnext (Canvas mcanvas, Paint mpaint) {
Mpaint.setcolor (Button.getcolorbase ());
Mpaint.setstyle (Paint.Style.FILL); Draw Border if (width >= height) {mcanvas.drawroundrect (new RECTF (CENTERX-WIDTH/2, CENTERY-HEIGHT/2, CenterX + W
IDTH/2, CenterY + height/2), Button.getround (), Button.getround (), mpaint);
Draw Text Mpaint.setcolor (Color.White);
Mpaint.setstrokewidth (Button.getstroketext ());
Mpaint.settextsize (Button.gettextsize ());
Paint.fontmetrics metrics = Mpaint.getfontmetrics (); int textWidth = (int) Mpaint.measuRetext (Button.gettext ());
int baseLine = (int) (CenterY + (metrics.bottom-metrics.top)/2-metrics.bottom);
Mcanvas.drawtext (Button.gettext (), CENTERX-TEXTWIDTH/2, BaseLine, Mpaint); else {mcanvas.drawoval (new RECTF (CENTERX-WIDTH/2, CENTERY-HEIGHT/2, CenterX + WIDTH/2, CenterY + HEIGHT/2
), Mpaint);
}
}
}
Then the second state, the progress bar status:
/** * Created by CCWXF on 2016/2/29.
* * Public class Progressstatus implements Buttonstatus {//Circle of child State private static final int status_once = 0;
private static final int status_twice = 1;
Spin the variable private static final int delay_progress = 10;
private static final int angle_progress = 5;
private static final int angle_default =-90;
private static final int andle_full = 270;
Private Animationbutton button;
private int width;
private int height;
private int CenterX;
private int centery;
private int radius;
private int status = Status_once;
Current progress private float progress = angle_default;
Private Handler Handler = new Handler ();
Public progressstatus (Animationbutton button, int width, int height, int centerx, int centery) {This.button = button;
This.width = width;
This.height = height;
This.centerx = CenterX;
This.centery = CenterY;
The start point of the drawing is the midpoint of the stroke, and if you do not subtract this value, the OnDraw will be incomplete.
This.radius = (width-button.getstrokeprogress ())/2;
Startprogress (); }
/**
*Start recursive rotation progress bar/private void startprogress () {handler.postdelayed (new Runnable () {@Override public void run () {if (Progress >= Andle_full)
{//If it is a manual end mode if (button.getmode () = = AnimationButton.Mode.Hand_Finish && button.isprogressstop ()) {//change state
Button.changestatus (status.finish, width, height, centerx, centery);
Return
}else{if (status = = status_once) {status = Status_twice; }else if (status = = Status_twice) {//If it is an automatic end mode, change the status at the end of the second progress if (button.getmode () = = AnimationButton.Mode.Auto_Fini
SH) {//Change state Button.changestatus (status.finish, width, height, centerx, centery);
Return
}else{status = Status_once;
}//Reset progress progress = Angle_default;
} Progress + = Angle_progress;
Button.invalidate ();
Handler.postdelayed (this, delay_progress);
}}, Delay_progress);
@Override public Status GetStatus () {return status.progress; @Override public boolean ontouchevent (Motionevent mevent){return false; @Override public void OnDraw (Canvas mcanvas, Paint mpaint) {if (status = status_once) {//Draw gray background ondrawcircle (MC
Anvas, Mpaint, Button.getcolorback ());
Draw Green Progress Ondrawarc (Mcanvas, Mpaint, Button.getcolorbase (), Angle_default, progress);
}else if (status = = Status_twice) {//Draw green background ondrawcircle (Mcanvas, Mpaint, Button.getcolorbase ());
Draw Gray Progress Ondrawarc (Mcanvas, Mpaint, Button.getcolorback (), Angle_default, progress); }/** * Draw an entire circle as background * @param mcanvas canvas * @param mpaint Brush * @param color/private void ondrawcircle (Canvas
Mcanvas, Paint mpaint, int color) {mpaint.setcolor (color);
Mpaint.setstrokewidth (Button.getstrokeprogress ());
Mpaint.setstyle (Paint.Style.STROKE);
Mcanvas.drawcircle (CenterX, CenterY, radius, mpaint);
/** * Draw one end arc * @param mcanvas canvas * @param mpaint Brush * @param color * @param start angle * @param stop angle * * private void Ondrawarc (Canvas mcanvas, Paint mpaint, int color, float start, float stop) {
Mpaint.setcolor (color);
Mpaint.setstrokewidth (Button.getstrokeprogress ());
Mpaint.setstyle (Paint.Style.STROKE);
The third parameter is the swept angle, and the starting point 0 defaults to the right Mcanvas.drawarc (new RECTF (Centerx-radius, Centery-radius, CenterX + radius, centery + radius),
Start, Stop-start, False, Mpaint);
}
}
Last state:
/** * Created by CCWXF on 2016/2/29.
* * Public class Finishstatus implements Buttonstatus {private static final int status_stretch = 0;
private static final int status_finish = 1;
private static final int stroke_over = 10;
private static final String Text_over = "√";
private static final int text_over_size = 40;
private static final int delay_stretch = 10;
private static final int pixel_stretch = 8;
Private Animationbutton button;
private int width;
private int height;
private int CenterX;
private int centery;
private int status = Status_stretch;
Private Handler Handler = new Handler ();
Public finishstatus (Animationbutton button, int width, int height, int centerx, int centery) {This.button = button;
This.width = width;
This.height = height;
This.centerx = CenterX;
This.centery = CenterY;
Startstretch (); /** * Start stretching background/private void Startstretch () {handler.postdelayed (new Runnable () {@Override public void run () {if (Width < Button.getmaXwidth ()) {width + = Pixel_stretch;
Button.invalidate ();
Handler.postdelayed (this, delay_stretch);
}else{width = button.getmaxwidth ();
if (status = = Status_stretch) {status = Status_finish;
} button.invalidate ();
}}, Delay_stretch);
@Override public Status GetStatus () {return status.finish;
@Override public boolean ontouchevent (Motionevent mevent) {return false;
@Override public void OnDraw (Canvas mcanvas, Paint mpaint) {//Draw background Mpaint.setcolor (Button.getcolorbase ());
Mpaint.setstyle (Paint.Style.FILL);
Mcanvas.drawroundrect (New RECTF (CENTERX-WIDTH/2, CENTERY-HEIGHT/2, CenterX + WIDTH/2, CenterY + HEIGHT/2),
Button.getround (), Button.getround (), mpaint);
Draw the picture if (status = = Status_finish) {mpaint.setcolor (color.white);
Mpaint.setstrokewidth (Stroke_over);
Mpaint.settextsize (text_over_size);
Paint.fontmetrics metrics = Mpaint.getfontmetrics ();
int textWidth = (int) mpaint.measuretext (text_over); int baSeline = (int) (HEIGHT/2 + (metrics.bottom-metrics.top)/2-metrics.bottom);
Mcanvas.drawtext (Text_over, (width-textwidth)/2, BaseLine, mpaint);
}
}
}
OK above is all the source code. Although I was summed up in three large states, but if the point of detail, probably need 9 states. This is the child state within the large state code. The
How to use it is also very simple, because most of the parameters have built-in values. &NBSP
/** * Created by CCWXF on 2016/2/29. * * Public class Mainactivity extends activity {@Override protected void onCreate (Bundle savedinstancestate) {Super.on
Create (savedinstancestate);
Setcontentview (R.layout.activity_main);
Final Animationbutton button = (Animationbutton) Findviewbyid (R.id.button); Button.settextsizetouch (25); Sets the font size when pressed, without setting a default value//Button.setstrokeprogress (10); Set the thickness of the progress bar, do not set a default value//Button.setcolorbase (Color.green); Sets the overall base color without setting a default value//Button.setcolorback (Color.gray); Set the background color of the progress bar, do not set a default value//Button.setstroke (3); Set the thickness of the border without setting a default value//Button.setstroketext (0); Sets the thickness of the text without setting a default value//Button.settextsize (30); Sets the font size of the text without setting a default value//Button.setround (30); Set rounded corners without setting a default value of Button.settext ("login"); Sets the text without setting a default value of Button.setmode (AnimationButton.Mode.Hand_Finish); Set the progress bar mode without setting a default value Mode.auto_finish Button.setonanimationbuttonclicklistener (new Animationbutton.onanimationbuttonclicklistener () {@Override public void OnClick () {//stopprogress method is only Button.setm Ode (AnimatiOnButton.Mode.Hand_Finish);
Button.stopprogress ();
}
});
}
}
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.