To draw a circle with a custom control, OnDraw() is used to draw the view, so as to output the view control that meets your needs

Observe the components of the ring:
Outer circle + middle percentage text + arc circle with changing progress
--->Analysis: the attributes required by each component constitute several key user-defined attributes
1: Color of outer circle
2: Color of arc progress circle
3: The color of the middle percentage text
4: Middle percentage text size
5: Width of the circle (as the width of the progress arc circle)
6: * there is also a circle progress in the home page. In order to be compatible with the circle progress of the home page, a custom attribute is added to draw the style of progress arc circle (solid [Fill], hollow [stroke])
Analysis finished -- > drawing steps:
1: Initialize the brush object in the constructor to get the custom attribute value
2: Override Ondraw method
---2.1: draw the outermost circle
-Key method canvas drawCircle(center, center, radius, paint); // Draw a circle
*: calculation radius, center point coordinates, brush settings
Center point coordinates
int center = getWidth() / 2; // Gets the x coordinate of the center of the circle
Radius:
int radius = (int) (center - roundWidth/2) -- drawing description is the easiest to understand
---2.2: draw percentage text in the middle
--Key method: canvas drawText(percent + "%", center - textWidth / 2, center + textSize / 2, paint); // Draw progress percentage
Measure the width of the text on the brush
float textWidth = paint.measureText(percent + "%");
Brush settings
The position of the drawn text is determined by the X and Y coordinate values of parameters 2 and 3 -- the position of the center point of the ring is displayed
10: Indicates where to start drawing. If you start drawing directly from the center point -- > the drawing description is the easiest to understand
-->Correct X=center - textWidth / 2; Y = center + textSize / 2 -- (because the y-axis value of the android coordinate system is opposite to that of the mathematical coordinate system, you can also draw a picture to illustrate that the textsize here can represent the height. After the paint.measureText measurement method is executed, the default text height is calculated according to the text size, which is equivalent to wrap_content, so textsize is the height value occupied by its own text)
*: the progress of drawing should be converted to percentage form: int percent = (int) (((float) progress / (float) max) * 100);
---2.3: draw progress arc circle
---Key method: canvas drawArc(oval, 0, 360 * progress / max, false, paint); // Draw an arc according to the progress
Parameter interpretation:
oval: the range profile of the drawn arc
0: from what angle do you start drawing
360 * progress / max: draw the area corresponding to the angle swept by the arc
false: does not contain the center of the circle. If true, it means that the center of the circle is included
paint: brush used for painting
Brush settings
paint.setStrokeWidth(roundWidth); // When setting the width of the progress arc circle, it must be consistent with the StrokeWidth of the outer circle to ensure that the coverage of the arc circle is the width of the outer circle
paint.setColor(roundProgressColor); // Sets the color of the progress
Arc range calculation
RectF oval = new RectF(center - radius, center - radius, center
+ radius, center + radius); ---> Drawing instructions are the easiest to understand

*Note: because progress is relative to the proportion of 100, and the arc is divided into 360 points according to the angle, the angle of the area swept by the specified parameters needs to be calculated and converted
=360 * progress / max(max=100)
Finally, it provides a method to set the progress and redraw the ring according to the progress
..... Circle drawing custom control analysis end|
RoundProgress
public class RoundProgress extends View { private Paint paint = new Paint(); private int roundColor; private int roundProgressColor; private int textColor; private float textSize; private float roundWidth; private int max = 100; private int progress = 50; public RoundProgress(Context context) { this(context, null); } public RoundProgress(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundProgress(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgress); //The color of the ring roundColor = mTypedArray.getColor(R.styleable.RoundProgress_roundColor, Color.RED); //The color of the circle progress roundProgressColor = mTypedArray.getColor(R.styleable.RoundProgress_roundProgressColor, Color.GREEN); //The color of the intermediate progress percentage text string textColor = mTypedArray.getColor(R.styleable.RoundProgress_textColor, Color.GREEN); //The font size of the string for the intermediate progress percentage textSize = mTypedArray.getDimension(R.styleable.RoundProgress_textSize, 15); //Width of the ring roundWidth = mTypedArray.getDimension(R.styleable.RoundProgress_roundWidth, 5); mTypedArray.recycle(); } @Override protected void onDraw(Canvas canvas) { //Step 1: draw an outermost circle paint.setColor(roundColor); paint.setStrokeWidth(roundWidth); paint.setStyle(Paint.Style.STROKE); paint.setAntiAlias(true); int center = getWidth() / 2; int radius = (int) (center - roundWidth / 2); canvas.drawCircle(center, center, radius, paint); //Step 2: draw the text in the middle float textWidth = paint.measureText(progress + "%"); paint.setColor(textColor); paint.setTextSize(textSize); paint.setStrokeWidth(0); canvas.drawText(progress + "%", center - textWidth / 2, center + textSize / 2, paint); //Step 3: /** * Parameter interpretation: * oval: Sketch the outline of the rectangular range contained by the arc circle * 0: Starting angle * 360 * progress / max: Scanned angle * false: Include center point * paint: Brush when drawing an arc */ RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius); paint.setColor(roundProgressColor); paint.setStrokeWidth(roundWidth); paint.setStyle(Paint.Style.STROKE); canvas.drawArc(oval, 0, 360 * progress / max, false, paint); } public void setProgress(int progress){ this.progress = progress; if(progress>100){ this.progress = 100; } postInvalidate(); } }
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="RoundProgress"> <attr name="roundColor" format="color"/> <attr name="roundProgressColor" format="color"/> <attr name="roundWidth" format="dimension"></attr> <attr name="textColor" format="color"/> <attr name="textSize" format="dimension"/> </declare-styleable> </resources>
<!-- Circle progress--> <cn.wh.ui.RoundProgress android:id="@+id/p_progresss" android:layout_width="120dp" android:layout_height="120dp" app:roundColor="@android:color/darker_gray" app:roundProgressColor="@android:color/holo_red_dark" app:roundWidth="10dp" app:textColor="#18b4ed" app:textSize="20sp"> </cn.wh.ui.RoundProgress>
private Runnable runnable = new Runnable() { @Override public void run() { int tempProgress = 0; try { while (tempProgress <= totalProgress) { pProgresss.setProgress(tempProgress); tempProgress++; Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } };