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:
- <?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>
<?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
- 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();
- }
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.
- @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);
- }
@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
- @Override
- protected synchronized void onDraw(Canvas canvas)
- {
- canvas.save();
- //The brush shifts to the specified paddingLeft, getHeight()/ 2 position, noting that the coordinates are all set to 0, 0 in the future
- 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();
- }
@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:
- /**
- * 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());
- }
/** * 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:
- 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();
- }
- }
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
- <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>
<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
- 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);
- }
- }
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.