Custom Circle progress bar Custom Countdown progress bar

Source: Internet
Author: User
Tags drawtext

Custom Circle progress bar Custom Countdown progress bar

Copyright NOTICE: Reprint must indicate this article transferred from Zhangjie's blog:

This control source is open source to Github:, Welcome to star.
Welcome to join my blog on the left side of the QQ Exchange Group to explore.

Effect Preview

Source Code Portal:Https://

Implementation and principle

This text round progress bar we have seen in many apps, such as the app Welcome page countdown, download file countdown, etc.

Analysis of the principle, maybe some students see this custom view on the panic, this is not to inherit the view Ah, is not to draw Ah, the answer is: yes. But let's not worry, it's really easy to achieve this effect. Let's take a look at core analysis and code with me.

Principle Analysis

First we observe that several components are required:
1. The round progress bar is gradually increased/decreased outside.
2. The display text in the middle of the round progress bar.
3. Round the round progress bar wrap the circle outside.
4. Fill color in the middle of the round progress bar.
5. Font color/Fill Color Click Color: ColorStateList class.

We analyzed the need for four parts. A look at the text, then the first thought of the nature is TextView , just can do less a font color record. The middle of the fill color (the prototype is not considered) color change when clicked, need ColorStateList class to record. The rest of the progress bar, Contour circle and fill circle is what we need to draw.

The process of stepping on a pit

In fact, for a long time did not write a custom view, some things have really forgotten, so write this view and put the previous pit tread again, in order to avoid other students also be pits, here I tread on the pit also recorded.

View Drawing Area

Here I have a problem, because we inherit the TextView text more is long, then draw out the circle length is the same, so the circle drawn on the TextView can only see part or ellipse. So we're going to View expand the drawing area. I first thought of the layout() method, because when View the parent layout is onLayout() called View layout() to let the child View layout, I rewrite the layout method:

@Overridepublicvoidlayout(intintintint bottom) {    int w = right - left;    int h = bottom - top;    int size = w > h ? w : h;    if (w > h) {        bottom += (size - h);    else {        right += (size - w);    }    super.layout(left, top, right, bottom);}

The principle of this code is wide and high, that large, the view to expand to this maximum value.

When I put a View on Layout , the effect is fine, but I put multiple View to linearlayout I found several View overlaps, oh Seth. It dawned on me that the Nima people Layout had specified the width of my plot area, and I forcibly occupied the other View . So, I should rewrite onmeasure () , and tell the parent Layout What size I want when I measure my height:

@OverrideprotectedvoidonMeasure(intint heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    int width = getMeasuredWidth();    int height = getMeasuredHeight();    int size = width > height ? width : height;    setMeasuredDimension(size, size);}

The meaning of this code is easier to understand, that is, super.onMeasure when measuring the width of the height of which large, the width is set to the largest of this value. Tell the father how Layout old I want to be, so when I draw I want to play as much as I can.

Implementation of Drawing view

OK, come to the key place, the front is all done and see how we draw our circle of several circles. It is necessary to rewrite the method in circle circles onDraw() .

First you need a brush:

new Paint();mPaint.setAntiAlias(true);// 抗锯齿
Get the drawing area.

We can get to the drawing area by Getdrawingrect (Rect) and calculate the radius of the circle by drawing the area.

new Rect();@OverrideprotectedvoidonDraw(Canvas canvas) {    getDrawingRect(bounds);//获取view的边界    int size = bounds.height() > bounds.width() ? bounds.width() : bounds.height();    float2// 计算出绘制圆的半径}
Draw a Fill circle

So we're going to have to use ColorStateList this to do an initialization and to support the definition of this attribute in XML:

// 默认透明填充。ColorStateList inCircleColors = ColorStateList.valueOf(Color.TRANSPARENT);privatevoidinitialize(Context ctx, AttributeSet attributeSet) {    TypedArray typedArray = ctx.obtainStyledAttributes(attributeSet, R.styleable.Progressbar);    inCircleColors = typedArray.getColorStateList(R.styleable.Progressbar_circle_color);    typedArray.recycle();}

Students who do not understand how to customize the view XML properties request Google for themselves.

The color of the filled circle is drawn according to the Click, Check, select State, because it is filled, so here Paint Style is FILL :

int0);mPaint.setStyle(Paint.Style.FILL);mPaint.setColor(circleColor);canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius - outLineWidth, mPaint);

The center is the center of the drawing area, and the radius is the width of the 绘制区域圆 radius minus 外部轮廓圆线 . This just fills the circles and the outer contour circles do not overlap.

Draw an outer border circle

This is simple because it is a hollow line, so Style Yes STROKE , then set the width of the line, the color of the brush:

2, mPaint);

The center of the Circle is the center of the drawing area, and the radius is half the width of the radius 绘制区域圆 minus 外部轮廓圆线 , so that the outer contour line and the inner fill circle close.

Draw TextViewThe word

For our drawing and our TextView own drawing does not overlap, we kill super.onDraw(canvas); , so here we have to put TextView word also to write up.

First get TextView The default brush, set TextView its own font color, anti-aliasing, for the sake of beauty we forcibly let the text center:

//画字Paint paint = getPaint();paint.setColor(getCurrentTextColor());paint.setAntiAlias(true);paint.setTextAlign(Paint.Align.CENTER);float2;canvas.drawText(getText().toString(), bounds.centerX(), textY, paint);
Draw a progress bar

The progress bar is not a circle. Oh, exactly, it's an arc,
The brush uses the default brush, sets the color, sets the width of the line, and Style STROKE finally specifies the drawing area and center point, angle:

RECTF Marcrect =NewRECTF (); Rect bounds =NewRect ();@Overrideprotected void OnDraw(Canvas canvas) {Getdrawingrect (bounds);//Get the boundary of the view...//Draw a progress bar arc. Mpaint.setcolor (Progresslinecolor);    Mpaint.setstyle (Paint.Style.STROKE);    Mpaint.setstrokewidth (Progresslinewidth); Mpaint.setstrokecap (Paint.Cap.ROUND);intDeletewidth = Progresslinewidth + outlinewidth;//Specify drawing areaMarcrect.set (Bounds.left + deletewidth/2, + deletewidth/2, Bounds.right-deletewidth/2, Bounds.bottom-deletewidth/2); Canvas.drawarc (Marcrect,0, the* Progress/ -,false, mpaint);}

Here the difficulty in specifying the drawing area, because the external contour lines can not be covered, so close to the outer contour of the interior painting, so to the outermost draw circle area, so to subtract (the outer Circle line width + progress bar width)/2 The boundary is the progress bar.

Complete code for drawing and measurement

Here the key code is finished, you can write a test yourself, I here to the full onDraw() and onMeasure() the source of the paste out:

Private intOutLineColor = Color.Black;Private intOutlinewidth =2;PrivateColorstatelist incirclecolors = colorstatelist.valueof (color.transparent);Private intCirclecolor;Private intProgresslinecolor = Color.Blue;Private intProgresslinewidth =8;PrivatePaint Mpaint =NewPaint ();PrivateRECTF Marcrect =NewRECTF ();Private intProgress = -;FinalRect bounds =NewRect ();@Overrideprotected void OnDraw(Canvas canvas) {//Get the boundary of the viewGetdrawingrect (bounds);intSize = Bounds.height () > Bounds.width ()? Bounds.width (): Bounds.height ();floatOuterradius = size/2;//Draw internal background    intCirclecolor = Incirclecolors.getcolorforstate (Getdrawablestate (),0);    Mpaint.setstyle (Paint.Style.FILL);    Mpaint.setcolor (Circlecolor); Canvas.drawcircle (Bounds.centerx (), Bounds.centery (), Outerradius-outlinewidth, mpaint);//Draw Border CircleMpaint.setstyle (Paint.Style.STROKE);    Mpaint.setstrokewidth (Outlinewidth);    Mpaint.setcolor (OutLineColor); Canvas.drawcircle (Bounds.centerx (), Bounds.centery (), Outerradius-outlinewidth/2, Mpaint);//stoopedPaint paint = getpaint ();    Paint.setcolor (Getcurrenttextcolor ()); Paint.setantialias (true); Paint.settextalign (Paint.Align.CENTER);floatTexty = Bounds.centery ()-(paint.descent () + paint.ascent ())/2; Canvas.drawtext (GetText (). toString (), Bounds.centerx (), texty, paint);//Draw progress barMpaint.setcolor (Progresslinecolor);    Mpaint.setstyle (Paint.Style.STROKE);    Mpaint.setstrokewidth (Progresslinewidth); Mpaint.setstrokecap (Paint.Cap.ROUND);intDeletewidth = Progresslinewidth + outlinewidth; Marcrect.set (Bounds.left + deletewidth/2, + deletewidth/2, Bounds.right-deletewidth/2, Bounds.bottom-deletewidth/2); Canvas.drawarc (Marcrect,0, the* Progress/ -,false, mpaint);}@Overrideprotected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {Super. Onmeasure (Widthmeasurespec, Heightmeasurespec);intLineWidth =4* (Outlinewidth + progresslinewidth);intwidth = Getmeasuredwidth ();intHeight = getmeasuredheight ();intSize = (Width > Height width:height) + linewidth; Setmeasureddimension (size, size);}

Above full Source: Https://, welcome star.

Copyright NOTICE: Reprint must indicate this article transferred from Zhangjie's blog:

Custom Circle progress bar Custom Countdown progress bar

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: 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.