Android creates a variety of progress bar implementations that can be as simple as

Source: Internet
Author: User
Tags drawtext getcolor

Reprint please indicate the source: http://blog.csdn.net/lmj623565791/article/details/43371299, this article from: "Zhang Hongyang Blog" 1, overview

Recently need to use the progress bar, faith does not repeat the principle of making wheels, on the GitHub search, see a few feel more good-looking progressbar, such as: Daimajia and so on. A simple look at the code, the basic is inherited from the view, thorough bottom of the custom a progress bar. Staring at the gorgeous scroll bar, suddenly feel, why to write a scroll bar through the view, the system has provided the ProgressBar and its characteristics, we do not need to build one, but the system is more ugly, different versions of the change is not necessarily the same. Then come our goal: Change the way the system ProgressBar.

?? Yes, we do not have to go from 0 to build a ProgressBar, although the long bad look, but the characteristics and stability is just, we need only for its full capacity is OK.

When it comes to cosmetic surgery, we all know that our control is drawn through the OnDraw (), then we just have to cover its OnDraw () method, write it down on the OK.

Yes, I created a public number, welcome attention, the left column to sweep.

?? Next, we post:

2, 1, Horizontal progress bar


2. Round progress bar


Yes, this is our progress bar effect, the horizontal imitation of the Daimajia progress bar look. But we inherit the sub-ProgressBar, simply for its entire capacity, the code is clear and understandable. Why is that easy to understand?

Horizontal that progress bar, everyone will DrawLine () and DrawText () bar, then through the getwidth () to get the width of the control, and then through the getprogress () to get the progress, proportional control of the length of the drawing line, the position of the word is not divided into minutes.

GitHub Source Address : Android-progressbarwidthnumber welcome you star or fork.


3. Realize

A horizontal scrollbar drawing must require some attributes, such as the color, width, color, size, and so on, of the progress that has been/is not reached.
Originally, I want to pass the system ProgressBar progressdrawable, extract some attributes from the inside to finish drawing the required parameters. But, in the end, it makes the code more complicated. So you end up using custom attributes instead. When it comes to custom attributes, you should be no stranger.

1, Horizontalprogressbarwithnumber 1. Custom Attributes

Values/attr_progress_bar.xml:

<?xml version= "1.0" encoding= "Utf-8"?><resources> <declare-styleable name= " Horizontalprogressbarwithnumber "> <attr name=" progress_unreached_color "format=" Color "/> <attr Name= "Progress_reached_color" format= "color"/> <attr name= "progress_reached_bar_height" format= "Dimension"/ > <attr name= "progress_unreached_bar_height" format= "Dimension"/> <attr name= "Progress_text_siz E "format=" Dimension "/> <attr name=" progress_text_color "format=" color "/> <attr name=" Progress _text_offset "format=" Dimension "/> <attr name=" progress_text_visibility "format=" enum "> <en Um name= "visible" value= "0"/> <enum name= "Invisible" value= "1"/> </attr> </declar e-styleable> <declare-styleable name= "Roundprogressbarwidthnumber" > <attr name= "radius" format= " Dimension "/> </declare-styleable></reSources> 

2. Acquisition in construction

public class Horizontalprogressbarwithnumber extends progressbar{private static final int default_text_size = 10;private static final int default_text_color = 0xfffc00d1;private static final int default_color_unreached_color = 0xffd3d6da;priv ATE static final int default_height_reached_progress_bar = 2;private static final int Default_height_unreached_progress_ BAR = 2;private static final int default_size_text_offset = 10;/** * Painter of all drawing things */protected Paint Mpain t = new Paint ();/** * Color of progress number */protected int mtextcolor = default_text_color;/** * Size of TEXT (sp) */p rotected int mtextsize = sp2px (default_text_size);/** * Offset of draw progress */protected int mtextoffset = dp2px (defaul T_size_text_offset);/** * height of reached progress bar */protected int mreachedprogressbarheight = dp2px (default_height _reached_progress_bar);/** * Color of reached BAR */protected int mreachedbarcolor = default_text_color;/** * Color of UNR eached Bar */protected int MUNreachedbarcolor = default_color_unreached_color;/** * height of unreached progress bar */protected int Munreachedprogres Sbarheight = dp2px (Default_height_unreached_progress_bar);/** * View width except padding */protected int mrealwidth; protected Boolean mifdrawtext = true;protected static final int VISIBLE = 0;public Horizontalprogressbarwithnumber (contex T context, AttributeSet Attrs) {This (context, attrs, 0);} Public Horizontalprogressbarwithnumber (context context, AttributeSet Attrs,int Defstyle) {Super (context, attrs, Defstyle); sethorizontalscrollbarenabled (true); Obtainstyledattributes (attrs); mpaint.settextsize (mTextSize); Mpaint.setcolor (Mtextcolor);}  /** * Get the styled attributes * * @param attrs */private void obtainstyledattributes (AttributeSet attrs) {//Init values From custom attributesfinal TypedArray attributes = GetContext (). Obtainstyledattributes (Attrs, R.styleable.horizontalprogressbarwithnumber); Mtextcolor = Attributes.getcolor ( R.styleable.horizontalprogressbarwithnumber_progress_text_color,default_text_color); mtextsize = (int) attributes.getdimension ( r.styleable.horizontalprogressbarwithnumber_progress_text_size,mtextsize); Mreachedbarcolor = Attributes.getColor (r.styleable.horizontalprogressbarwithnumber_progress_reached_color,mtextcolor); MUnReachedBarColor = Attributes.getcolor (r.styleable.horizontalprogressbarwithnumber_progress_unreached_color,default_color_ Unreached_color); mreachedprogressbarheight = (int) attributes.getdimension ( R.styleable.horizontalprogressbarwithnumber_progress_reached_bar_height,mreachedprogressbarheight); Munreachedprogressbarheight = (int) attributes.getdimension (r.styleable.horizontalprogressbarwithnumber_progress_ Unreached_bar_height,munreachedprogressbarheight); mtextoffset = (int) attributes.getdimension ( r.styleable.horizontalprogressbarwithnumber_progress_text_offset,mtextoffset); int textVisible = Attributes.getInt (r.styleable.horizontalprogressbarwithnumber_progress_text_visibility,visible); if (textVisible! = VISIBLE) {Mifdrawtext = false;} Attributes.recycle ();}

Well, it looks like the code is pretty long, but it's all about getting custom properties, nothing technical.


3, Onmeasure

Just now not out of the OnDraw inside write, why to change onmeasure it, mainly because all of our properties such as the width of the progress bar to customize the user, so our measurements have to be slightly changed.

@Overrideprotected synchronized void onmeasure (int widthmeasurespec,int heightmeasurespec) {int heightmode = Measurespec.getmode (HEIGHTMEASURESPEC); if (heightmode! = measurespec.exactly) {Float textHeight = (mpaint.descent () + Mpaint.ascent ()); int exceptheight = (int) (Getpaddingtop () + getpaddingbottom () + Math.max (Math.max ( Mreachedprogressbarheight,munreachedprogressbarheight), Math.Abs (TextHeight)); Heightmeasurespec = Measurespec.makemeasurespec (exceptheight,measurespec.exactly);} Super.onmeasure (Widthmeasurespec, heightmeasurespec);}

Width We do not change, so the custom property does not involve width, height, only consider the situation is not exactly (the user explicitly specified, we do not care), according to padding and the width of the progress bar to calculate what you want, if not exactly, we do exceptheight encapsulation , which is passed to the control to measure height.

After the measurement, it's our OnDraw.

4, OnDraw

@Overrideprotected synchronized void OnDraw (canvas canvas) {canvas.save ();//Brush pan to the specified paddingleft, getheight ()/2 position, Note that the coordinates hereafter are 0,0canvas.translate (Getpaddingleft (), GetHeight ()/2), Boolean noneedbg = false;//Current progress and total value of float radio =  Getprogress () * 1.0f/getmax ();//reached width float progressposx = (int) (MREALWIDTH * radio);//Drawn text string text = Getprogress () + "%";//Get the width and height of the font float textWidth = mpaint.measuretext (text); float textHeight = (mpaint.descent () + mpaint.ascent ())/2; If you arrive at the end, the unreachable progress bar does not need to draw if (Progressposx + textWidth > mrealwidth) {progressposx = mrealwidth-textwidth;noneedbg = True ;} Draw the progress you have reached float EndX = progressposx-mtextoffset/2;if (EndX > 0) {mpaint.setcolor (mreachedbarcolor); Mpaint.setstrok Ewidth (mreachedprogressbarheight); canvas.drawline (0, 0, endx, 0, mpaint);} Draw text if (Mifdrawtext) {mpaint.setcolor (Mtextcolor); Canvas.drawtext (text, Progressposx,-textheight, mpaint);} Draw an unreachable progress bar if (!noneedbg) {Float start = progressposx + MTEXTOFFSET/2 + Textwidth;mpaint.setcoloR (Munreachedbarcolor); Mpaint.setstrokewidth (munreachedprogressbarheight); Canvas.drawline (start, 0, mRealWidth, 0, Mpaint);} Canvas.restore ();}  @Overrideprotected void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH); mrealwidth = W-getpaddingright ()-Getpaddingleft ();}

In fact, the core method is OnDraw, but, OnDraw is also very simple, draw lines, draw text, draw lines, end.


There are also two simple helper methods:

/** * DP 2 px *  * @param dpval */protected int dp2px (int dpval) {return (int) typedvalue.applydimension (typedvalue.comp Lex_unit_dip,dpval, Getresources (). Getdisplaymetrics ());} /** * SP 2 px *  * @param spval * @return */protected int sp2px (int spval) {return (int) typedvalue.applydimension (Typed Value.complex_unit_sp,spval, Getresources (). Getdisplaymetrics ());}

Well, to this our horizontal progress is over, is not very simple ~ ~ If you are a custom view, you also have to consider the progress update, consider the state of destruction and recovery, and so complex things.

Next look at our Roundprogressbarwidthnumber round progress bar.

2, Roundprogressbarwidthnumber

The round progress bar and the horizontal progress bar basic variables are all consistent, so I let Roundprogressbarwidthnumber extends Horizontalprogressbarwithnumber.

What needs to be changed is the measurement and OnDraw:

Full code:

Package Com.zhy.view;import Android.content.context;import Android.content.res.typedarray;import Android.graphics.canvas;import Android.graphics.paint.cap;import Android.graphics.paint.style;import Android.graphics.rectf;import Android.util.attributeset;import Com.zhy.library.view.r;public Class Roundprogressbarwidthnumber Extendshorizontalprogressbarwithnumber {/** * Mradius of view */private int mRadius = dp2px (3 0);p ublic roundprogressbarwidthnumber (Context context) {This (context, null);} Public Roundprogressbarwidthnumber (context context, AttributeSet Attrs) {Super (context, attrs); Mreachedprogressbarheight = (int) (munreachedprogressbarheight * 2.5f); TypedArray ta = context.obtainstyledattributes (attrs,r.styleable.roundprogressbarwidthnumber); MRadius = (int) Ta.getdimension (R.styleable.roundprogressbarwidthnumber_radius, Mradius); Ta.recycle (); mTextSize = sp2px (14); Mpaint.setstyle (Style.stroke); Mpaint.setantialias (true); Mpaint.setdither (true); Mpaint.setstrokecap (Cap.ROUND);} @Overrideprotected 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 + PaintW Idth); widthmeasurespec = Measurespec.makemeasurespec (exceptwidth,measurespec.exactly);} Super.onmeasure (Heightmeasurespec, heightmeasurespec);} @Overrideprotected synchronized void OnDraw (canvas canvas) {String text = getprogress () + "%";//Mpaint.gettextbounds (Tex T, 0, Text.length (), mtextbound), float textWidth = mpaint.measuretext (text), float textHeight = (mpaint.descent () + Mpaint . Ascent ()/2;canvas.save (); Canvas.translate (Getpaddingleft (), Getpaddingtop ()); Mpaint.setstyle (style.stroke);//Draw unreaded Barmpaint.setcolor (Munreachedbarcolor); Mpaint.setstrokewidth (munreachedprogressbarheight); Canvas.drawcircle (Mradius, Mradius, Mradius, mpaint);//Draw reached Barmpaint.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);//Draw Textmpaint.setstyle (style.f ILL); Canvas.drawtext (text, MRADIUS-TEXTWIDTH/2, mradius-textheight,mpaint); Canvas.restore ();}}

First obtains its proprietary property Mradius, then according to this property to measure, the measurement completes the drawing;

What about the drawing process?

Draw a smaller circle first, and then draw a slightly thicker arc, stacked together. Text, draw in the middle ~ ~ ~ Overall, there is no amount of code.

OK, two progress bar is here, is not found much simpler. Overall design, there are some problems, if the extraction of a baseprogressbar for public properties, and then different kinds of progress bar inheritance to implement their own measurement and appearance, so the structure may be clearer ~ ~ ~


4. Using Layout files
<scrollview xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http// Schemas.android.com/tools "xmlns:zhy=" Http://schemas.android.com/apk/res-auto "android:layout_width=" Match_        Parent "android:layout_height=" match_parent "> <linearlayout android:layout_width=" match_parent " android:layout_height= "match_parent" android:orientation= "vertical" android:padding= "25DP" > < Com.zhy.view.HorizontalProgressBarWithNumber android:id= "@+id/id_progressbar01" android:layout_width = "Match_parent" android:layout_height= "wrap_content" android:layout_margintop= "50dip" and roid:padding= "5DP"/> <com.zhy.view.horizontalprogressbarwithnumber android:layout_width= "m Atch_parent "android:layout_height=" wrap_content "android:layout_margintop=" 50dip "Androi          d:padding= "5DP" android:progress= "50"  Zhy:progress_text_color= "#ffF53B03" zhy:progress_unreached_color= "#ffF7C6B7"/> <com.zhy.view.ro            Undprogressbarwidthnumber android:id= "@+id/id_progress02" android:layout_width= "Match_parent"            android:layout_height= "Wrap_content" android:layout_margintop= "50dip" android:padding= "5DP" android:progress= "/> <com.zhy.view.roundprogressbarwidthnumber android:layout_width=" m Atch_parent "android:layout_height=" wrap_content "android:layout_margintop=" 50dip "Androi d:padding= "5DP" android:progress= "zhy:progress_reached_bar_height=" 20DP "zhy:progress _text_color= "#ffF53B03" zhy:radius= "60DP"/> </LinearLayout></ScrollView>

mainactivity
Package Com.zhy.sample.progressbar;import Android.app.activity;import Android.os.bundle;import Android.os.Handler; Import Com.zhy.annotation.log;import Com.zhy.view.horizontalprogressbarwithnumber;public class MainActivity extends Activity {private horizontalprogressbarwithnumber mprogressbar;private static final int msg_progress_update = 0x110; Private Handler Mhandler = new Handler () {@Logpublic void Handlemessage (Android.os.Message msg) {int progress = MPROGRESSB Ar.getprogress (); mprogressbar.setprogress (++progress); if (progress >=) {mhandler.removemessages (MSG_ Progress_update);} Mhandler.sendemptymessagedelayed (msg_progress_update, 100);}; @Log @overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_main); Mprogressbar = (Horizontalprogressbarwithnumber) Findviewbyid (R.ID.ID_PROGRESSBAR01); Mhandler.sendemptymessage (msg_progress_update);}}

Finally, what is the purpose of this blog? Just to say, like ProgressBar such a control, if you just want to change the appearance of the display, there is no need to create from 0, carbon OnDraw can, of course, is a personal point of view, put forward for your reference.


SOURCE Click to download


Group number: 423372824


Bo Master part of the video has been online, if you do not like boring text, please poke (first record, look forward to your support):

Video Directory Address: I recorded a video tutorial



Android creates a variety of progress bar implementations that can be as simple as

Related Article

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.