Android custom controls to achieve color progressive circular progress

First glance, the effect of custom controls is shown below.

The effect of this control is still very common, but it is limited to the Android system which does not provide such effect control, so it can only enrich its own clothing.

In the Android project, some of the Android system source controls need to be implemented because of the requirements of the product requirements or the requirements of the UI effect diagram. So custom controls are required to achieve the relevant effects. Therefore, custom controls are also a basic work for the development of Android. This article introduces the relevant process of custom controls based on the inheritance of View and the use of Canvas to draw graphics.

1. customize CircleProgressBar, inherit View, and implement the constructor of the response.

The code is as follows:

/ * * * * *

* Created by WangChunLei

* * /

Public class GradientProgressBar extends View {

Public GradientProgressBar (Context context) {

Super (context);

Init ();

}

Public GradientProgressBar (Context context, AttributeSet attrs) {

Super (context, attrs);

Init ();

}

Public GradientProgressBar (Context context, AttributeSet attrs, int defStyleAttr) {

Super (context, attrs, defStyleAttr);

Init ();

}

}

The init method is the initialization method for the related brush. The init method code is as follows:

Private void init () {

BackCirclePaint = new Paint ();

BackCirclePaint.setStyle (Paint.Style.STROKE);

BackCirclePaint.setAntiAlias (true);

BackCirclePaint.setColor (Color.LTGRAY);

BackCirclePaint.setStrokeWidth (circleBorderWidth);

/ / backCirclePaint.setMaskFilter (New BlurMaskFilter (20, BlurMaskFilter.Blur.OUTER));

GradientCirclePaint = new Paint ();

GradientCirclePaint.setStyle (Paint.Style.STROKE);

GradientCirclePaint.setAntiAlias (true);

GradientCirclePaint.setColor (Color.LTGRAY);

GradientCirclePaint.setStrokeWidth (circleBorderWidth);

LinePaint = new Paint ();

LinePaint.setColor (Color.WHITE);

LinePaint.setStrokeWidth (5);

TextPaint = new Paint ();

TextPaint.setAntiAlias (true);

TextPaint.setTextSize (textSize);

TextPaint.setColor (Color.BLACK);

}

2. the width and height of the control control -onMeasure

OnMeasure is the first step of custom control. The purpose is to measure the width and height of the control. The code of the onMeasure method is as follows:

@Override

Protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {

Int measureWidth = MeasureSpec.getSize (widthMeasureSpec);

Int measureHeight = MeasureSpec.getSize (heightMeasureSpec);

SetMeasuredDimension (Math.min (measureWidth, measureHeight), Math.min (measureWidth, measureHeight));

}

After the onMeasure code is posted, it is estimated that it is rarely seen as simple as the measurement process such a simple onMeasure, do not mind, the interested colleagues can refine this measurement process, the different measurement modes are processed and measured separately, so that the control is better and more perfect. In the onMeasure method, we get the desired width and height separately and take the smaller size as the width and height of the control.

3., in turn, draw different components of the control.

Because the control is directly inherited from the View, it does not need to reprocess the onLayout method, which is one of the differences between the custom View and the custom ViewGroup, but the inheritance of the ViewGroup does not necessarily have to rewrite the onMeasure.

To achieve the effect as shown, we need to implement the following steps in turn.

(1) draw a gray hollow ring

(2) draw a ring of color gradient

(3) draw the white lines divided on the ring

(4) draw percentage words and so on.

If the content of the rendering process is intersecting with the content previously drawn, the content that is drawn later will cover the content before it is drawn. According to the steps mentioned above, the following member variables will be generated during the rendering process.

/ * circular arc linewidth * /

Private float circleBorderWidth = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_DIP, 20, getResources ().GetDisplayMetrics ());

/ * internal margin * /

Private float circlePadding = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_DIP, 20, getResources ().GetDisplayMetrics ());

/ * font size * /

Private float textSize = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_SP, 50, getResources ().GetDisplayMetrics ());

/ * to draw a circumference brush /

Private Paint backCirclePaint;

/ * a brush drawing a circumferential white line

Private Paint linePaint;

/ *

Private Paint textPaint;

/ * percentage * / /

Private int percent = 0;

/ * the gradient of the circle color array * /

Private int[] gradientColorArray = new int[]{Color.GREEN, Color.parseColor (" #fe751a&quot); Color.parseColor (" #13be23"); "

Private Paint gradientCirclePaint;

3.1 draw a gray hollow ring

The code is as follows:

//1. draws a gray background circle

Canvas.drawArc (

New RectF (circlePadding * 2, circlePadding * 2,

GetMeasuredWidth () – circlePadding * 2, getMeasuredHeight () – circlePadding * 2, -90, 360, false, backCirclePaint);

Among them, -90 is the initial angle to draw the arc, and the 360 is the angle drawn by the circle, that is, sweepAngle..

3.2 draw a ring of color gradient

//2. draws the color gradient circle

LinearGradient linearGradient = new LinearGradient (circlePadding, circlePadding).

GetMeasuredWidth () – circlePadding,

GetMeasuredHeight () – circlePadding,

GradientColorArray, null, Shader.TileMode.MIRROR);

GradientCirclePaint.setShader (linearGradient);

GradientCirclePaint.setShadowLayer (10, 10, 10, Color.RED);

Canvas.drawArc (

New RectF (circlePadding * 2, circlePadding * 2,

GetMeasuredWidth () – circlePadding * 2, getMeasuredHeight () – circlePadding * 2, -90, (float) (percent / 100) * 360, false, gradientCirclePaint);

Among them, linearGradient is the shadow of Paint, which needs to be set for the color gradient effect of the arc. The application frequency in the daily development is not high, but it is true that it can achieve a very ideal color gradient effect.

3.3 draw the white lines divided on the ring

When drawing the white lines on the arc, some simple operations are needed, such as the starting coordinates of the lines startX, the startY and the terminating coordinates of the lines, stopX, stopY, etc., which are easily calculated using a simple trigonometric function. In the effect, the circular arc is divided into 100 points with white lines. Each class is 1, which can meet the percentage of the int type and the proportion of the effect map.

/ / / radius

Float radius = (getMeasuredWidth () – circlePadding * 3) / 2;

//X axis center point coordinates

Int centerX = getMeasuredWidth () / 2;

//3. draws 100 line segments to cut into hollow arcs

For (float I = 0; I < 360; I + = 3.6) {

Double rad = I * Math.PI / 180;

Float startX = (float) (centerX + (radius circleBorderWidth) * Math.sin (RAD));

Float startY = (float) (centerX + (radius circleBorderWidth) * Math.cos (RAD));

Float stopX = (float) (centerX + radius * Math.sin (RAD) + 1);

Float stopY = (float) (centerX + radius * Math.cos (RAD) + 1);

Canvas.drawLine (startX, startY, stopX, stopY, linePaint);

}

3.4 draw percentage text and finally draw percentage text. In order to draw text, in order to keep the center point of the text and the origin of the arc, it is necessary to measure the width and height of the text first, and then carry out some simple calculations. The principle is no longer described. I believe that everyone is better than me.

//4. drawing text

Float textWidth = textPaint.measureText (percent + "%");

Int textHeight = (int) (Math.ceil (textPaint.getFontMetrics ().Descent – textPaint.getFontMetrics ().Ascent) + 2);

Canvas.drawText (percent + "%" centerX textWidth / 2, centerX + textHeight / 4, textPaint);

Finally, a common method is changed to change the percentage of display. The code is as follows:

/ * * * * *

* setting percentage

*

* @param percent

* * /

Public void setPercent (int percent) {

If (percent < 0) {

Percent = 0;

} else if (percent > 100) {

Percent = 100;

}

This.percent = percent;

Invalidate ();

}

At this point, all drawing processes are outlined, and 130 lines of code can achieve very cool effects. Finally, paste the complete code of the project for students who are too lazy to see the implementation process, O (O) ha ha.

Package com.example.myview;

Import android.content.Context;

Import android.graphics.*;

Import android.util.AttributeSet;

Import android.util.TypedValue;

Import android.view.View;

/ * * * * *

* Created by WangChunLei

* * /

Public class GradientProgressBar extends View {

/ * circular arc linewidth * /

Private float circleBorderWidth = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_DIP, 20, getResources ().GetDisplayMetrics ());

/ * internal margin * /

Private float circlePadding = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_DIP, 20, getResources ().GetDisplayMetrics ());

/ * font size * /

Private float textSize = TypedValue.applyDimension (TypedValue.COMPLEX_UNIT_SP, 50, getResources ().GetDisplayMetrics ());

/ * to draw a circumference brush /

Private Paint backCirclePaint;

/ * a brush drawing a circumferential white line

Private Paint linePaint;

/ *

Private Paint textPaint;

/ * percentage * / /

Private int percent = 0;

/ * the gradient of the circle color array * /

Private int[] gradientColorArray = new int[]{Color.GREEN, Color.parseColor (" #fe751a&quot); Color.parseColor (" #13be23"); "

Private Paint gradientCirclePaint;

Public GradientProgressBar (Context context) {

Super (context);

Init ();

}

Public GradientProgressBar (Context context, AttributeSet attrs) {

Super (context, attrs);

Init ();

}

Public GradientProgressBar (Context context, AttributeSet attrs, int defStyleAttr) {

Super (context, attrs, defStyleAttr);

Init ();

}

Private void init () {

BackCirclePaint = new Paint ();

BackCirclePaint.setStyle (Paint.Style.STROKE);

BackCirclePaint.setAntiAlias (true);

BackCirclePaint.setColor (Color.LTGRAY);

BackCirclePaint.setStrokeWidth (circleBorderWidth);

/ / backCirclePaint.setMaskFilter (New BlurMaskFilter (20, BlurMaskFilter.Blur.OUTER));

GradientCirclePaint = new Paint ();

Leave a Reply

Your email address will not be published. Required fields are marked *