Android Custom View Circle progress bar button _android

Source: Internet
Author: User
Tags getcolor

Introduced

Today at work, a friend asked me how to implement a button-style progress bar, first to see what he needs to achieve the effect of the picture.

Similar to the ordinary circular progress bar, only the middle of the place has two states, not started, paused state. And he says the function of the circular progress has been realized. So we just need to deal with the two states in the middle.

First look at the implementation of the effect of the diagram:

It said that we only need to deal with the change in the middle State, for the progress of the processing of direct use of the Hong Yang article to achieve:
http://blog.csdn.net/lmj623565791/article/details/43371299

The following is a concrete implementation.

Concrete implementation

Customize the implementation or follow the official steps, I also wrote an article before the step to customize the view, interested friends can look at: Android Custom view of the official routine.

In order to fully explain, the following will refer to the custom of the circular progress bar, knowing that the implementation of the progress can skip some steps directly.

1. Create View

Observe the outer ring progress bar to be implemented with two progress: one to represent the default circle and the other to represent the progress of the color. So here's a definition of two progress bars with a wide-range color. It must be a radius to draw the circle.

There are three small steps to creating a view

(1), defining attributes

<declare-styleable name= "Buttoncircleprogressbar" >
<!--no progress colors--> <attr name=
"Progress_ Unreached_color "format=" color "/>
<!--progress colors--> <attr name=" Progress_reached_color "format="
Color "/>
<!--progress bar high-->
<attr name="
progress_reached_bar_height "format=" Dimension "/> <!--without progress-->
<attr name= "Progress_unreached_bar_height" format= "Dimension"/>
<!-- Radius of the Circle-->
<attr name= "radius" format= "Dimension"/>
</declare-styleable>

(1), defining property variables, and getting properties in the constructor method

private static final int default_text_color = 0XFFFC00D1;
private static final int default_color_unreached_color = 0XFFD3D6DA;
private static final int default_height_reached_progress_bar = 2;
private static final int default_height_unreached_progress_bar = 2;
/** * The status of this view currently;
* Private Status mstatus = Status.end;
/** * Painter of all drawing things/protected Paint mpaint = new Paint (); /** * Height of reached progress bar */protected int mreachedprogressbarheight = DP2PX (default_height_reached_progress_ba
R);
/** * Color of reached bar */protected int mreachedbarcolor = Default_text_color;
/** * Color of unreached Bar */protected int munreachedbarcolor = Default_color_unreached_color; /** * Height of unreached progress bar */protected int munreachedprogressbarheight = DP2PX (default_height_unreached_progr
Ess_bar);
/** * The length of triangle * * private int trianglelength;
/** * Use path to draw triangle * * Private path MPath; /** * Mradius of view * * private int Mradius = dp2px (30); Public Buttoncircleprogressbar {This (context,null);} public Buttoncircleprogressbar , AttributeSet attrs) {This [context, attrs,0];} public Buttoncircleprogressbar (context, AttributeSet attrs, int DEFSTYLEATTR) {Super (context, attrs, defstyleattr);//init values from custom attributes final TypedArray attributes = G
Etcontext (). Obtainstyledattributes (Attrs, R.styleable.buttoncircleprogressbar);
Mreachedbarcolor = attributes. GetColor (R.styleable.buttoncircleprogressbar_progress_reached_color, Color.BLUE); Munreachedbarcolor = attributes. GetColor (R.styleable.buttoncircleprogressbar_progress_unreached_color, DEFAULT_
Color_unreached_color); Mreachedprogressbarheight = (int) attributes. Getdimension (r.styleable.buttoncircleprogressbar_progress_reached_
Bar_height, Mreachedprogressbarheight); Munreachedprogressbarheight = (int) attributes. Getdimension (R.styleable.buttoncircleprogressbar_progress_ Unreached_bar_Height, munreachedprogressbarheight);
Mradius = (int) attributes.getdimension (R.styleable.buttoncircleprogressbar_radius, Mradius);
Trianglelength = Mradius;
Attributes.recycle ();
Mpaint.setstyle (Paint.Style.STROKE);
Mpaint.setantialias (TRUE);
Mpaint.setdither (TRUE);
Mpaint.setstrokecap (Paint.Cap.ROUND); MPath = new Path ();//need path to draw triangle} public Status GetStatus () {return mstatus;} public void SetStatus (Stat US status) {Mstatus = status; Invalidate ();} public enum status{end, starting}

Gets some of the underlying properties, where mstatus is used to indicate the status of the current view: End code ends, starting is in progress. We use these two states to determine how to draw to the appropriate effect. SetStatus is provided for the Staus setting state.

MPath is used to draw a triangle when drawing is not started.

2, the layout of the processing view

This step is mainly to measure the appropriate width and height in the Onmeasure method.

@Override
protected synchronized void onmeasure (int widthmeasurespec, int heightmeasurespec) {
int heightmode = Measurespec.getmode (HEIGHTMEASURESPEC);
int widthmode = Measurespec.getmode (widthmeasurespec);
int paintwidth = Math.max (mreachedprogressbarheight,
munreachedprogressbarheight);
if (Heightmode!= measurespec.exactly) {
int exceptheight = (int) (Getpaddingtop () + getpaddingbottom ()
+ Mradius * 2 + paintwidth);
Heightmeasurespec = Measurespec.makemeasurespec (exceptheight,
measurespec.exactly);
}
if (Widthmode!= measurespec.exactly) {
int exceptwidth = (int) (Getpaddingleft () + getpaddingright ()
+ Mradius * 2 + paintwidth);
Widthmeasurespec = Measurespec.makemeasurespec (exceptwidth,
measurespec.exactly);
}
Super.onmeasure (Widthmeasurespec, Heightmeasurespec);
}

You only need to handle situations where the width is not specified precisely, and the value is calculated by padding plus the entire circle and the width of the paint.

Next is the third step, draw the effect.

3. Draw View

To make it clearer, here's the progress of drawing the circle, and the state of the circle in the middle.

(1), Draw a circle

@Override
protected synchronized void OnDraw (Canvas Canvas) {
super.ondraw (Canvas);
Canvas.save ();
Canvas.translate (Getpaddingleft (), Getpaddingtop ());
Mpaint.setstyle (Paint.Style.STROKE);
Draw unreaded Bar
Mpaint.setcolor (munreachedbarcolor);
Mpaint.setstrokewidth (munreachedprogressbarheight);
Canvas.drawcircle (Mradius, Mradius, Mradius, mpaint);
Draw reached Bar
Mpaint.setcolor (mreachedbarcolor);
Mpaint.setstrokewidth (mreachedprogressbarheight);
float sweepangle = getprogress () * 1.0F/GETMAX () * 360;
Canvas.drawarc (New RECTF (0, 0, Mradius * 2, Mradius * 2), 0,
Sweepangle, False, Mpaint);

Through Canvas.drawcircle (Mradius, Mradius, Mradius, Mpaint), draw a circle in the default state. Then change the color of the brush and draw the arc according to the progress.

(2), draw the middle state.

The first is an unfinished case, with a triangle in the middle. We use path to draw a triangle, mainly by moveTo (float x, float y) to set the first point and then by LineTo (float x, float y) to connect a triangle. Then set paint to fill.

The first point is set here to the vertex of the upper-left corner of the triangle.

So what's the first point?

Here we draw a equilateral, setting the edge length equal to the radius.

The x-coordinate of the first point should be the diameter of the circle minus the height of the triangle divided by 2, namely:

 
 

The y coordinates are: mradius-(TRIANGLELENGTH/2)

The second point chooses the lower-left corner of the triangle, the x-coordinate, the Y-value as the RADIUS plus the half of the length of the Edge: mradius+ (TRIANGLELENGTH/2)

The third point is the right point, and the x-coordinate of the X point is obviously the x-coordinate of the first point plus the height of the triangle.
That is: (float) (leftx+math.sqrt (3.0)/2*trianglelength), the Y-point coordinate is the radius mradius.

Finally, the first point is connected to a triangle.

The complete code for the MPath setting is as follows

public class Buttoncircleprogressbar extends ProgressBar {
...
.. MPath = new Path ();//need path to draw triangle
trianglelength = Mradius;
float LEFTX = (float) ((2*mradius-math.sqrt (3.0)/2*trianglelength)/2);
float realx = (float) (leftx+leftx*0.2);
Mpath.moveto (realx,mradius-(TRIANGLELENGTH/2));
Mpath.lineto (realx,mradius+ (TRIANGLELENGTH/2));
Mpath.lineto ((float) (realx+math.sqrt (3.0)/2*trianglelength), Mradius);
Mpath.lineto (realx,mradius-(TRIANGLELENGTH/2));
}

Here with the Realx set to leftx twice times, because I feel the triangle set in the middle of the effect is not very good, so let him in the original based on the increase of 0.2 times times the distance.

With the MPath variable, you can draw a triangle in the OnDraw that doesn't start, look at the code

@Override
protected synchronized void OnDraw (Canvas Canvas) {
super.ondraw (Canvas);
Canvas.save ();
Canvas.translate (Getpaddingleft (), Getpaddingtop ());
....
if (mstatus==status.end) {//Not starting state, brush fill
mpaint.setstyle (Paint.Style.FILL);
Canvas.drawpath (mpath,mpaint)/Direct DrawPath
}else{
mpaint.setstyle (Paint.Style.STROKE);
Mpaint.setstrokewidth (dp2px (5));
Canvas.drawline (mradius*2/3,mradius*2/3,mradius*2/3,2*mradius*2/3,mpaint);
Canvas.drawline (2*mradius-(MRADIUS*2/3), mradius*2/3,2*mradius-(MRADIUS*2/3), 2*mradius*2/3,mpaint);
Canvas.restore ();
}

The in-progress state is to draw two lines, the first line x is directly set to 2/3 times times the radius, the starting Y point is 2/3 times times, and the end is 2/3 times times the start Y point.

For the other line, the X-point diameter minus the mradius*2/3,y point coordinates is the same as the previous line.

This completes the OnDraw method.

4, Processing user interaction

As for the download update progress, the control only do the status display, so this step does not need to use the words of their own set click event can be.

Use

<?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"
xmlns:app= "http://schemas.android.com/apk/" Res-auto "
android:paddingbottom=" @dimen/activity_vertical_margin "
android:paddingleft=" @dimen/activity _horizontal_margin "
android:paddingright=" @dimen/activity_horizontal_margin "
android:paddingtop=" @ Dimen/activity_vertical_margin "
tools:context=" com.qiangyu.test.buttoncircleprogress.MainActivity ">
<com.qiangyu.test.buttoncircleprogress.view.buttoncircleprogressbar
android:id= "@+id/progressBar "
android:layout_width=" wrap_content "
android:layout_height=" wrap_content "
android:layout_ margintop= "50dip"
android:padding= "5DP"
android:progress= "/>"
</RelativeLayout>

Activity to set the Click event to modify the state, specifically according to their own logical processing.

public class Mainactivity extends Appcompatactivity {private Buttoncircleprogressbar mprogressbar; private static final
int msg_progress_update = 0x110;
private int progress; Private Handler Mhandler = new Handler () {public void Handlemessage (Android.os.Message msg) {progress = Mprogressbar.get
Progress ();
Mprogressbar.setprogress (++progress); if (progress >=) {mhandler.removemessages (msg_progress_update); progress = 0; Mprogressbar.setstatus (
BUTTONCIRCLEPROGRESSBAR.STATUS.END);
Mprogressbar.setprogress (0);
}else{mhandler.sendemptymessagedelayed (msg_progress_update, 100);}};
}; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (
R.layout.activity_main);
Mprogressbar = (Buttoncircleprogressbar) Findviewbyid (R.id.progressbar); Mprogressbar.setonclicklistener (New View.onclicklistener () {@Override public void OnClick (view view) {if Mprogressbar . GetStatus () = = ButtonCircleProgressBar.Status.Starting) {Mprogressbar. SetStatus (BUTTONCIRCLEPROGRESSBAR.STATUS.END);
Mhandler.removemessages (msg_progress_update); }else{mhandler.sendemptymessage (msg_progress_update); Mprogressbar.setstatus (
ButtonCircleProgressBar.Status.Starting);
}
}
}); }
}

OK, here is a circular progress bar button. I hope to help you, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.