Android can be as simple as creating a variety of progress bars

Keywords: Android xml github encoding

For reprinting, please indicate the source: http://blog.csdn.net/lmj623565791/article/details/43371299 This article is from: [Zhang Hongyang's Blog]

1. Overview

Recently, I searched github for several ProgressBars that looked good, such as daimajia, on the principle of not repeating wheels, using a progress bar.After a brief look at the code below, it's basically inherited from View, which completely defines a progress bar.Looking at that gorgeous scrollbar, I suddenly feel why I want to write a scrollbar through View. The ProgressBar and its features are already provided by the system. We don't need to rebuild one, but the system is ugly and different versions are not necessarily the same.So here's our goal: to change the look of the system ProgressBar.(

_Yes, there is no need to build a ProgressBar from 0. Although they are not good-lo ok ing, they still have just the characteristics and stability. We just need to groom them.(

When it comes to cosmetic surgery, we all know that our controls are drawn by onDraw(), so we just need to override its onDraw() method and write it down by ourselves.(

Yes, I created one WeChat Public number, please pay attention, just sweep up the left column.

_Next, let's paste a picture of the effect:

2. Effects

1. Horizontal progress bar


2. Round progress bar


Yes, this is our progress bar effect, which simulates the daimajia progress bar horizontally.However, we inherit the child ProgressBar, simply for its entire content, and the code is clear and easy to understand.Why is it easy to understand?

Horizontal that progress bar, you will draw Line () and drawText(), then get the width of the control through getWidth(), then get the progress through getProgress(), control the length of the drawing line proportionally, the position of words is not a minute matter.

github source address: Android-ProgressBarWidthNumber Welcome to star or fork.


3. Realization

Horizontal scrollbar drawing certainly requires some attributes, such as the color, width, color, size of the text, and so on.
Originally, I wanted to extract some attributes from ProgressBar's progressDrawable system to complete the parameters needed for drawing.Ultimately, however, it complicates the code.Ultimately, you'll use custom attributes instead.When it comes to custom attributes, you should be familiar with them.

1,HorizontalProgressBarWithNumber

1. Custom Properties

values/attr_progress_bar.xml:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <declare-styleable name="HorizontalProgressBarWithNumber">  
  5.         <attr name="progress_unreached_color" format="color" />  
  6.         <attr name="progress_reached_color" format="color" />  
  7.         <attr name="progress_reached_bar_height" format="dimension" />  
  8.         <attr name="progress_unreached_bar_height" format="dimension" />  
  9.         <attr name="progress_text_size" format="dimension" />  
  10.         <attr name="progress_text_color" format="color" />  
  11.         <attr name="progress_text_offset" format="dimension" />  
  12.         <attr name="progress_text_visibility" format="enum">  
  13.             <enum name="visible" value="0" />  
  14.             <enum name="invisible" value="1" />  
  15.         </attr>  
  16.     </declare-styleable>  
  17.       
  18.     <declare-styleable name="RoundProgressBarWidthNumber">  
  19.         <attr name="radius" format="dimension" />  
  20.     </declare-styleable>  
  21.   
  22. </resources>  
<?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_size" format="dimension" />
        <attr name="progress_text_color" format="color" />
        <attr name="progress_text_offset" format="dimension" />
        <attr name="progress_text_visibility" format="enum">
            <enum name="visible" value="0" />
            <enum name="invisible" value="1" />
        </attr>
    </declare-styleable>

    <declare-styleable name="RoundProgressBarWidthNumber">
        <attr name="radius" format="dimension" />
    </declare-styleable>

</resources>

2. Getting in Construction

  1. public class HorizontalProgressBarWithNumber extends ProgressBar  
  2. {  
  3.   
  4.     private static final int DEFAULT_TEXT_SIZE = 10;  
  5.     private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1;  
  6.     private static final int DEFAULT_COLOR_UNREACHED_COLOR = 0xFFd3d6da;  
  7.     private static final int DEFAULT_HEIGHT_REACHED_PROGRESS_BAR = 2;  
  8.     private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2;  
  9.     private static final int DEFAULT_SIZE_TEXT_OFFSET = 10;  
  10.   
  11.     /** 
  12.      * painter of all drawing things 
  13.      */  
  14.     protected Paint mPaint = new Paint();  
  15.     /** 
  16.      * color of progress number 
  17.      */  
  18.     protected int mTextColor = DEFAULT_TEXT_COLOR;  
  19.     /** 
  20.      * size of text (sp) 
  21.      */  
  22.     protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);  
  23.   
  24.     /** 
  25.      * offset of draw progress 
  26.      */  
  27.     protected int mTextOffset = dp2px(DEFAULT_SIZE_TEXT_OFFSET);  
  28.   
  29.     /** 
  30.      * height of reached progress bar 
  31.      */  
  32.     protected int mReachedProgressBarHeight = dp2px(DEFAULT_HEIGHT_REACHED_PROGRESS_BAR);  
  33.   
  34.     /** 
  35.      * color of reached bar 
  36.      */  
  37.     protected int mReachedBarColor = DEFAULT_TEXT_COLOR;  
  38.     /** 
  39.      * color of unreached bar 
  40.      */  
  41.     protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR;  
  42.     /** 
  43.      * height of unreached progress bar 
  44.      */  
  45.     protected int mUnReachedProgressBarHeight = dp2px(DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR);  
  46.     /** 
  47.      * view width except padding 
  48.      */  
  49.     protected int mRealWidth;  
  50.       
  51.     protected boolean mIfDrawText = true;  
  52.   
  53.     protected static final int VISIBLE = 0;  
  54.   
  55.     public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs)  
  56.     {  
  57.         this(context, attrs, 0);  
  58.     }  
  59.   
  60.     public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs,  
  61.             int defStyle)  
  62.     {  
  63.         super(context, attrs, defStyle);  
  64.           
  65.         setHorizontalScrollBarEnabled(true);  
  66.   
  67.         obtainStyledAttributes(attrs);  
  68.   
  69.         mPaint.setTextSize(mTextSize);  
  70.         mPaint.setColor(mTextColor);  
  71.   
  72.     }  
  73.       
  74.     /** 
  75.      * get the styled attributes 
  76.      *  
  77.      * @param attrs 
  78.      */  
  79.     private void obtainStyledAttributes(AttributeSet attrs)  
  80.     {  
  81.         // init values from custom attributes  
  82.         final TypedArray attributes = getContext().obtainStyledAttributes(  
  83.                 attrs, R.styleable.HorizontalProgressBarWithNumber);  
  84.   
  85.         mTextColor = attributes  
  86.                 .getColor(  
  87.                         R.styleable.HorizontalProgressBarWithNumber_progress_text_color,  
  88.                         DEFAULT_TEXT_COLOR);  
  89.         mTextSize = (int) attributes.getDimension(  
  90.                 R.styleable.HorizontalProgressBarWithNumber_progress_text_size,  
  91.                 mTextSize);  
  92.   
  93.         mReachedBarColor = attributes  
  94.                 .getColor(  
  95.                         R.styleable.HorizontalProgressBarWithNumber_progress_reached_color,  
  96.                         mTextColor);  
  97.         mUnReachedBarColor = attributes  
  98.                 .getColor(  
  99.                         R.styleable.HorizontalProgressBarWithNumber_progress_unreached_color,  
  100.                         DEFAULT_COLOR_UNREACHED_COLOR);  
  101.         mReachedProgressBarHeight = (int) attributes  
  102.                 .getDimension(  
  103.                         R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height,  
  104.                         mReachedProgressBarHeight);  
  105.         mUnReachedProgressBarHeight = (int) attributes  
  106.                 .getDimension(  
  107.                         R.styleable.HorizontalProgressBarWithNumber_progress_unreached_bar_height,  
  108.                         mUnReachedProgressBarHeight);  
  109.         mTextOffset = (int) attributes  
  110.                 .getDimension(  
  111.                         R.styleable.HorizontalProgressBarWithNumber_progress_text_offset,  
  112.                         mTextOffset);  
  113.   
  114.         int textVisible = attributes  
  115.                 .getInt(R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility,  
  116.                         VISIBLE);  
  117.         if (textVisible != VISIBLE)  
  118.         {  
  119.             mIfDrawText = false;  
  120.         }  
  121.         attributes.recycle();  
  122.     }  
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;
    private 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 mPaint = new Paint();
    /**
     * color of progress number
     */
    protected int mTextColor = DEFAULT_TEXT_COLOR;
    /**
     * size of text (sp)
     */
    protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);

    /**
     * offset of draw progress
     */
    protected int mTextOffset = dp2px(DEFAULT_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 unreached bar
     */
    protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR;
    /**
     * height of unreached progress bar
     */
    protected int mUnReachedProgressBarHeight = 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(Context 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 attributes
        final 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 long, but it's all about getting custom attributes. It's not very technical.


3,onMeasure

Just now it's OK to write out of onDraw. Why change onMeasure? It's mainly because all of our attributes, such as the width of the progress bar, are customized by users, so our measurements have to change a little.

  1. @Override  
  2. protected synchronized void onMeasure(int widthMeasureSpec,  
  3.         int heightMeasureSpec)  
  4. {  
  5.     int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  6.   
  7.     if (heightMode != MeasureSpec.EXACTLY)  
  8.     {  
  9.   
  10.         float textHeight = (mPaint.descent() + mPaint.ascent());  
  11.         int exceptHeight = (int) (getPaddingTop() + getPaddingBottom() + Math  
  12.                 .max(Math.max(mReachedProgressBarHeight,  
  13.                         mUnReachedProgressBarHeight), Math.abs(textHeight)));  
  14.   
  15.         heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight,  
  16.                 MeasureSpec.EXACTLY);  
  17.     }  
  18.     super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  19.   
  20. }  
   @Override
    protected 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 does not change, so custom attributes don't involve width or height. Consider only situations that aren't EXACTLY (we don't care if the user explicitly specifies it). Calculate what you want based on padding and progress bar width. If not EXACTLY, we do exceptHeight encapsulation and pass it in to the control to measure height.

When you've finished measuring, it's time for our onDraw ~~

4,onDraw

  1. @Override  
  2.     protected synchronized void onDraw(Canvas canvas)  
  3.     {  
  4.         canvas.save();  
  5.         //The brush shifts to the specified paddingLeft, getHeight()/ 2 position, noting that the coordinates are all set to 0, 0 in the future  
  6.         canvas.translate(getPaddingLeft(), getHeight() / 2);  
  7.   
  8.         boolean noNeedBg = false;  
  9.         //Ratio of current progress to total value  
  10.         float radio = getProgress() * 1.0f / getMax();  
  11.         //Reached Width  
  12.         float progressPosX = (int) (mRealWidth * radio);  
  13.         //Drawn Text  
  14.         String text = getProgress() + "%";  
  15.   
  16.         //Get the width and height of the font  
  17.         float textWidth = mPaint.measureText(text);  
  18.         float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;  
  19.   
  20.         //If the end is reached, the unreached progress bar does not need to be drawn  
  21.         if (progressPosX + textWidth > mRealWidth)  
  22.         {  
  23.             progressPosX = mRealWidth - textWidth;  
  24.             noNeedBg = true;  
  25.         }  
  26.   
  27.         //Draw progress reached  
  28.         float endX = progressPosX - mTextOffset / 2;  
  29.         if (endX > 0)  
  30.         {  
  31.             mPaint.setColor(mReachedBarColor);  
  32.             mPaint.setStrokeWidth(mReachedProgressBarHeight);  
  33.             canvas.drawLine(00, endX, 0, mPaint);  
  34.         }  
  35.       
  36.         //Draw Text  
  37.         if (mIfDrawText)  
  38.         {  
  39.             mPaint.setColor(mTextColor);  
  40.             canvas.drawText(text, progressPosX, -textHeight, mPaint);  
  41.         }  
  42.   
  43.         //Draw unreached progress bar  
  44.         if (!noNeedBg)  
  45.         {  
  46.             float start = progressPosX + mTextOffset / 2 + textWidth;  
  47.             mPaint.setColor(mUnReachedBarColor);  
  48.             mPaint.setStrokeWidth(mUnReachedProgressBarHeight);  
  49.             canvas.drawLine(start, 0, mRealWidth, 0, mPaint);  
  50.         }  
  51.   
  52.         canvas.restore();  
  53.   
  54.     }  
  55.   
  56.     @Override  
  57.     protected void onSizeChanged(int w, int h, int oldw, int oldh)  
  58.     {  
  59.         super.onSizeChanged(w, h, oldw, oldh);  
  60.         mRealWidth = w - getPaddingRight() - getPaddingLeft();  
  61.   
  62.     }  
@Override
    protected synchronized void onDraw(Canvas canvas)
    {
        canvas.save();
        //Brush shifts to the specified paddingLeft, getHeight ()/ 2 position, note that the coordinates are all set to 0, 0
        canvas.translate(getPaddingLeft(), getHeight() / 2);

        boolean noNeedBg = false;
        //Ratio of current progress to total value
        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 the end is reached, the unreached progress bar does not need to be drawn
        if (progressPosX + textWidth > mRealWidth)
        {
            progressPosX = mRealWidth - textWidth;
            noNeedBg = true;
        }

        //Draw progress reached
        float endX = progressPosX - mTextOffset / 2;
        if (endX > 0)
        {
            mPaint.setColor(mReachedBarColor);
            mPaint.setStrokeWidth(mReachedProgressBarHeight);
            canvas.drawLine(0, 0, endX, 0, mPaint);
        }

        //Draw text
        if (mIfDrawText)
        {
            mPaint.setColor(mTextColor);
            canvas.drawText(text, progressPosX, -textHeight, mPaint);
        }

        //Draw unreached 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();

    }

    @Override
    protected 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, drawing lines, drawing text, drawing lines, end.


There are two simple ways to help:

  1. /** 
  2.  * dp 2 px 
  3.  *  
  4.  * @param dpVal 
  5.  */  
  6. protected int dp2px(int dpVal)  
  7. {  
  8.     return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,  
  9.             dpVal, getResources().getDisplayMetrics());  
  10. }  
  11.   
  12. /** 
  13.  * sp 2 px 
  14.  *  
  15.  * @param spVal 
  16.  * @return 
  17.  */  
  18. protected int sp2px(int spVal)  
  19. {  
  20.     return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,  
  21.             spVal, getResources().getDisplayMetrics());  
  22.   
  23. }  
 /**
     * dp 2 px
     * 
     * @param dpVal
     */
    protected int dp2px(int dpVal)
    {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, getResources().getDisplayMetrics());
    }

    /**
     * sp 2 px
     * 
     * @param spVal
     * @return
     */
    protected int sp2px(int spVal)
    {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, getResources().getDisplayMetrics());

    }

Okay, that's the end of our horizontal progress, isn't it easy ~~If you're a custom View, you'll have to consider updates to your programs, state destruction and recovery, and so on.

Next, let's look at the progress bar of our RoundProgressBarWidthNumber circle.

2,RoundProgressBarWidthNumber 

The circular progress bar and the horizontal progress bar basic variables are the same, so I let RoundProgressBarWidthNumber extends HorizontalProgressBarWithNumber.

Then all that needs to change is measurement and onDraw:

Full code:

  1. package com.zhy.view;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Paint.Cap;  
  7. import android.graphics.Paint.Style;  
  8. import android.graphics.RectF;  
  9. import android.util.AttributeSet;  
  10.   
  11. import com.zhy.library.view.R;  
  12.   
  13. public class RoundProgressBarWidthNumber extends  
  14.         HorizontalProgressBarWithNumber {  
  15.     /** 
  16.      * mRadius of view 
  17.      */  
  18.     private int mRadius = dp2px(30);  
  19.   
  20.     public RoundProgressBarWidthNumber(Context context) {  
  21.         this(context, null);  
  22.     }  
  23.   
  24.     public RoundProgressBarWidthNumber(Context context, AttributeSet attrs) {  
  25.         super(context, attrs);  
  26.   
  27.         mReachedProgressBarHeight = (int) (mUnReachedProgressBarHeight * 2.5f);  
  28.         TypedArray ta = context.obtainStyledAttributes(attrs,  
  29.                 R.styleable.RoundProgressBarWidthNumber);  
  30.         mRadius = (int) ta.getDimension(  
  31.                 R.styleable.RoundProgressBarWidthNumber_radius, mRadius);  
  32.         ta.recycle();  
  33.   
  34.         mTextSize = sp2px(14);  
  35.   
  36.         mPaint.setStyle(Style.STROKE);  
  37.         mPaint.setAntiAlias(true);  
  38.         mPaint.setDither(true);  
  39.         mPaint.setStrokeCap(Cap.ROUND);  
  40.   
  41.     }  
  42.   
  43.     @Override  
  44.     protected synchronized void onMeasure(int widthMeasureSpec,  
  45.             int heightMeasureSpec) {  
  46.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  47.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
  48.   
  49.         int paintWidth = Math.max(mReachedProgressBarHeight,  
  50.                 mUnReachedProgressBarHeight);  
  51.   
  52.         if (heightMode != MeasureSpec.EXACTLY) {  
  53.   
  54.             int exceptHeight = (int) (getPaddingTop() + getPaddingBottom()  
  55.                     + mRadius * 2 + paintWidth);  
  56.             heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight,  
  57.                     MeasureSpec.EXACTLY);  
  58.         }  
  59.         if (widthMode != MeasureSpec.EXACTLY) {  
  60.             int exceptWidth = (int) (getPaddingLeft() + getPaddingRight()  
  61.                     + mRadius * 2 + paintWidth);  
  62.             widthMeasureSpec = MeasureSpec.makeMeasureSpec(exceptWidth,  
  63.                     MeasureSpec.EXACTLY);  
  64.         }  
  65.   
  66.         super.onMeasure(heightMeasureSpec, heightMeasureSpec);  
  67.   
  68.     }  
  69.   
  70.     @Override  
  71.     protected synchronized void onDraw(Canvas canvas) {  
  72.   
  73.         String text = getProgress() + "%";  
  74.         // mPaint.getTextBounds(text, 0, text.length(), mTextBound);  
  75.         float textWidth = mPaint.measureText(text);  
  76.         float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;  
  77.   
  78.         canvas.save();  
  79.         canvas.translate(getPaddingLeft(), getPaddingTop());  
  80.         mPaint.setStyle(Style.STROKE);  
  81.         // draw unreaded bar  
  82.         mPaint.setColor(mUnReachedBarColor);  
  83.         mPaint.setStrokeWidth(mUnReachedProgressBarHeight);  
  84.         canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);  
  85.         // draw reached bar  
  86.         mPaint.setColor(mReachedBarColor);  
  87.         mPaint.setStrokeWidth(mReachedProgressBarHeight);  
  88.         float sweepAngle = getProgress() * 1.0f / getMax() * 360;  
  89.         canvas.drawArc(new RectF(00, mRadius * 2, mRadius * 2), 0,  
  90.                 sweepAngle, false, mPaint);  
  91.         // draw text  
  92.         mPaint.setStyle(Style.FILL);  
  93.         canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight,  
  94.                 mPaint);  
  95.   
  96.         canvas.restore();  
  97.   
  98.     }  
  99.   
  100. }  
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 extends
        HorizontalProgressBarWithNumber {
    /**
     * mRadius of view
     */
    private int mRadius = dp2px(30);

    public 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);

    }

    @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(heightMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {

        String text = getProgress() + "%";
        // mPaint.getTextBounds(text, 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 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);
        // draw text
        mPaint.setStyle(Style.FILL);
        canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight,
                mPaint);

        canvas.restore();

    }

}

First acquire its proprietary property mRadius, and then measure based on it to complete the drawing of the measurement;

How about the drawing process?

Draw a slightly thinner circle first, then a slightly coarser radian, and they will overlap.Text, drawn in the middle ~~the whole, has no amount of code.

Okay, that's the end of the two progress bars. Did you find it much easier?Overall, there are some problems with the design. If you extract a BaseProgressBar to get common attributes, then progress bar inheritance in different shapes implements their own measurements and shapes separately, the structure may be clearer ~~


4. Use

Layout file

  1. <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     xmlns:zhy="http://schemas.android.com/apk/res-auto"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent" >  
  6.   
  7.     <LinearLayout  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent"  
  10.         android:orientation="vertical"  
  11.         android:padding="25dp" >  
  12.   
  13.         <com.zhy.view.HorizontalProgressBarWithNumber  
  14.             android:id="@+id/id_progressbar01"  
  15.             android:layout_width="match_parent"  
  16.             android:layout_height="wrap_content"  
  17.             android:layout_marginTop="50dip"  
  18.             android:padding="5dp" />  
  19.   
  20.          
  21.   
  22.         <com.zhy.view.HorizontalProgressBarWithNumber  
  23.             android:layout_width="match_parent"  
  24.             android:layout_height="wrap_content"  
  25.             android:layout_marginTop="50dip"  
  26.             android:padding="5dp"  
  27.             android:progress="50"  
  28.             zhy:progress_text_color="#ffF53B03"  
  29.             zhy:progress_unreached_color="#ffF7C6B7" />  
  30.   
  31.         <com.zhy.view.RoundProgressBarWidthNumber  
  32.             android:id="@+id/id_progress02"  
  33.             android:layout_width="match_parent"  
  34.             android:layout_height="wrap_content"  
  35.             android:layout_marginTop="50dip"  
  36.             android:padding="5dp"  
  37.             android:progress="30" />  
  38.   
  39.         <com.zhy.view.RoundProgressBarWidthNumber  
  40.             android:layout_width="match_parent"  
  41.             android:layout_height="wrap_content"  
  42.             android:layout_marginTop="50dip"  
  43.             android:padding="5dp"  
  44.             android:progress="50"  
  45.             zhy:progress_reached_bar_height="20dp"  
  46.             zhy:progress_text_color="#ffF53B03"  
  47.             zhy:radius="60dp" />  
  48.        
  49.     </LinearLayout>  
  50.   
  51. </ScrollView>  
<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"
            android:padding="5dp" />



        <com.zhy.view.HorizontalProgressBarWithNumber
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dip"
            android:padding="5dp"
            android:progress="50"
            zhy:progress_text_color="#ffF53B03"
            zhy:progress_unreached_color="#ffF7C6B7" />

        <com.zhy.view.RoundProgressBarWidthNumber
            android:id="@+id/id_progress02"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dip"
            android:padding="5dp"
            android:progress="30" />

        <com.zhy.view.RoundProgressBarWidthNumber
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dip"
            android:padding="5dp"
            android:progress="50"
            zhy:progress_reached_bar_height="20dp"
            zhy:progress_text_color="#ffF53B03"
            zhy:radius="60dp" />

    </LinearLayout>

</ScrollView>

MainActivity

  1. package com.zhy.sample.progressbar;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6.   
  7. import com.zhy.annotation.Log;  
  8. import com.zhy.view.HorizontalProgressBarWithNumber;  
  9.   
  10. public class MainActivity extends Activity {  
  11.   
  12.     private HorizontalProgressBarWithNumber mProgressBar;  
  13.     private static final int MSG_PROGRESS_UPDATE = 0x110;  
  14.   
  15.     private Handler mHandler = new Handler() {  
  16.         @Log  
  17.         public void handleMessage(android.os.Message msg) {  
  18.             int progress = mProgressBar.getProgress();  
  19.             mProgressBar.setProgress(++progress);  
  20.             if (progress >= 100) {  
  21.                 mHandler.removeMessages(MSG_PROGRESS_UPDATE);  
  22.                   
  23.             }  
  24.             mHandler.sendEmptyMessageDelayed(MSG_PROGRESS_UPDATE, 100);  
  25.         };  
  26.     };  
  27.   
  28.     @Log  
  29.     @Override  
  30.     protected void onCreate(Bundle savedInstanceState) {  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.activity_main);  
  33.         mProgressBar = (HorizontalProgressBarWithNumber) findViewById(R.id.id_progressbar01);  
  34.         mHandler.sendEmptyMessage(MSG_PROGRESS_UPDATE);  
  35.   
  36.     }  
  37.   
  38. }  
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() {
        @Log
        public void handleMessage(android.os.Message msg) {
            int progress = mProgressBar.getProgress();
            mProgressBar.setProgress(++progress);
            if (progress >= 100) {
                mHandler.removeMessages(MSG_PROGRESS_UPDATE);

            }
            mHandler.sendEmptyMessageDelayed(MSG_PROGRESS_UPDATE, 100);
        };
    };

    @Log
    @Override
    protected 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?That's to say, a control like ProgressBar, if you just want to change the way it looks, you don't need to create it from 0 at all. You can copy onDraw, which is your personal point of view for your reference.


Source Click Download  




Posted by alarik149 on Fri, 07 Jun 2019 09:08:08 -0700