One, foreword

Android custom View is advanced advanced indispensable content, daily work, often encounter products, UI design flashy interface. When the control system can not meet the development needs, you can only do it yourself a effect.

This article with a custom View beginners manual masturbation effect, through the custom View to achieve circular progress bar function, each line of code has comments, ensure easy to understand, do not understand your message hit me!!

Two, achieve the effect

1. Realize the effect drawing


2. Download the source code: Click download

3. Step analysis

To achieve the above effects, there are mainly four steps:

  1. Custom attributes
  2. Draw the circle
  3. Draw the arc
  4. Update progress bar
  5. Percentage of drawing progress

Three, code implementation

1. Customize attributes

In order to realize the colorful ring progress bar, the color, size, style and other attributes are removed from the custom attributes, so that it can be set directly in the XML file, which can be more convenient to use according to the requirements of the project. Here is a detailed explanation of the steps of custom attributes:

  1. Creating attrs.xml in the res/values folder will require custom attribute declaration definitions:
  <attr name="annulusColor" format="color"/>// Ring color
  <attr name="loadColor" format="color"/>// Ring progress bar load color
  <attr name="annulusWidth" format="dimension"/>// Ring width
  <attr name="progress" format="integer"/>// loop progress
  <attr name="textColor" format="color"/>// Text color
 <attr name="textSize" format="dimension"/>// Text font size  <attr name="progressType">// Annular progress bar type: 0. Solid 1. Hollow  <enum name="fill" value="0"/>  <enum name="stroke" value="1"/>  </attr>  <attr name="isShowText">// Whether to display text: 0. Display 1  <enum name="yes" value="0"/>  <enum name="no" value="1"/>  </attr>   <declare-styleable name="AnnulusCustomizeView">  <attr name="annulusColor"/>  <attr name="loadColor"/>  <attr name="annulusWidth"/>  <attr name="progress"/>  <attr name="textColor"/>  <attr name="textSize"/>  <attr name="progressType"/>  <attr name="isShowText"/>  </declare-styleable> Copy the code
  1. Override the constructor with three arguments in the custom View class and get the custom property:
// Get custom attributes
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AnnulusCustomizeView, defStyleAttr, 0);
int indexCount = a.getIndexCount();
for (int i = 0; i < indexCount; i++) {
    int aIndex = a.getIndex(i);
 switch (aIndex) {  case R.styleable.AnnulusCustomizeView_annulusWidth:  mAnnulusWidth = a.getDimensionPixelSize(aIndex,  (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,  10. getResources().getDisplayMetrics()));  break;  case R.styleable.AnnulusCustomizeView_annulusColor:  mAnnulusColor = a.getColor(aIndex, Color.BLACK);  break;  case R.styleable.AnnulusCustomizeView_loadColor:  mLoadColor = a.getColor(aIndex, Color.BLACK);  break;  case R.styleable.AnnulusCustomizeView_textColor:  mTextColor = a.getColor(aIndex, Color.BLACK);  break;  case R.styleable.AnnulusCustomizeView_textSize:  mTextSize = a.getDimensionPixelSize(aIndex,  (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,  15. getResources().getDisplayMetrics()));  break;  case R.styleable.AnnulusCustomizeView_progressType:  mProgressType = a.getInt(aIndex, 1);  break;  case R.styleable.AnnulusCustomizeView_isShowText:  mIsShowText = a.getInt(aIndex, 1);  break;  case R.styleable.AnnulusCustomizeView_progress:  mProgress = a.getInt(aIndex, 10);  break;  } } a.recycle(); Copy the code
  1. To apply custom attributes to the layout page XML, remember to add a namespace to the parent layout:

xmlns:app="http://schemas.android.com/apk/res-auto"

  <com.caobo.customizeview.view.AnnulusCustomizeView
      android:layout_marginTop="100dp"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
 app:layout_constraintTop_toTopOf="parent"  android:id="@+id/mAnnulusCustomizeView3"  android:layout_width="200dp"  android:layout_height="200dp"  android:padding="20dp"  app:isShowText="yes"  app:annulusColor="#BB1"  app:annulusWidth="15dp"  app:loadColor="#CCC"  app:progress="0"  app:progressType="stroke"  app:textColor="# 000000"  app:textSize="50dp" /> Copy the code

The above will complete the declaration of custom attributes, access, application of the whole process, Android comes with a lot of View source code has related attributes, you can look up the source code to learn, in fact, is very simple.

2. Draw a circle

Circle drawing canvas.drawCircle() is completed, defining the position of x and y axes of the circle, radius size, and setting paintbrush related properties can be easily completed.

// TODO:Draw the circle
// Get the circular coordinates
int centre = getWidth() / 2;
// Get the radius
int radius = centre - mAnnulusWidth / 2;
// unaliased mPaint.setAntiAlias(true); // Set the brush width mPaint.setStrokeWidth(mAnnulusWidth); // Set the hollow mPaint.setStyle(Paint.Style.STROKE); // Set the brush color mPaint.setColor(mAnnulusColor); canvas.drawCircle(centre, centre, radius, mPaint); Copy the code

3. Draw arcs

Arcs are the areas that are swept when the progress bar is updated. Arcs are drawn using the Canvas.drawarc () method. The specific drawing method parameters are not described in detail here.

switch (mProgressType) {
  case STROKE:
      mPaint.setStyle(Paint.Style.STROKE);
      // Define the boundary between the shape and size of the arc
      RectF ovalStroke = new RectF(centre - radius, centre - radius, centre + radius, centre + radius);
 / * *StartAngle: Start at -90°, which is 12 o 'clock of the clock.SweepAngle: Angle swept by an arcUseCenter: Sets whether our arcs are rounded when drawing. True has no effect when painting.style.stroke* /  canvas.drawArc(ovalStroke, -90, mProgress * 360 / maxProgress, false, mPaint);  break;   case FILL:  mPaint.setStyle(Paint.Style.FILL);  // Define the boundary between the shape and size of the arc  RectF ovalFill = new RectF(centre - radius - mAnnulusWidth / 2, centre - radius - mAnnulusWidth / 2. centre + radius + mAnnulusWidth / 2, centre + radius + mAnnulusWidth / 2);  canvas.drawArc(ovalFill, -90, mProgress * 360 / maxProgress, true, mPaint);  break; } Copy the code

Arc drawing can be done easily by defining the boundaries of the shape and size of the arc according to the relevant custom attributes.

Update the progress bar

In this paper, thread sleep is used to simulate progress bar update, which will be updated in real time according to download or upload progress in real projects.

Call the postInvalidate() method in the custom View to refresh the drawing View in real time to achieve the progress bar update effect.

/ * ** Analog data* /
private void setProgress(a) {
    new Thread() {
 @Override  public void run(a) {  for (int i = 1; i <= 100; i++) {  mAnnulusCustomizeView1.setProgress(i);  mAnnulusCustomizeView2.setProgress(i);  mAnnulusCustomizeView3.setProgress(i);  try {  Thread.sleep(100);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }  }.start(); } Copy the code
/ * ** Update View based on external progress delivery *
 * @param progress
* /
public synchronized voidSetProgress (final int progress) {  this.mProgress = progress;  new Thread() {  @Override  public void run(a) {  if (mProgress == 100) {} / / to complete  postInvalidate();  }  }.start(); } Copy the code

5. Draw text

The progress bar text is displayed in the center of the ring, and the position of the x and y axes of the text, as well as the size and color of the text, can be drawn using the canvas.drawtext () method.

  1. Measure text height

The text 0% — 100% height is fixed, so you can measure the text height in advance using the paint.gettextbounds () method:

// Returns the smallest rectangle at the border, where the user measures the height of the text because the height of the text is fixed according to the font size
mPaint.getTextBounds("%".0."%".length(), rect);
Copy the code
  1. Measure text width

Get the text width based on the percentage of real-time update progress using the paint.measureText () method

// Measure the text width
float measureTextWidth = mPaint.measureText(percentContext + "%");
Copy the code
  1. Define the x and y positions of the text

Since the position of x and Y axes of the text is not in the center of the text, but in the lower right corner of the text, attention should be paid to the measurement method of the position of x and Y axes of the text:

int x = centre - measureTextWidth / 2;
int y = centre + rect.height() / 2;
Copy the code
  1. Text rendering

With all of this in place, you can begin to draw the text.

canvas.drawText(percentContext + "%", centre - measureTextWidth / 2, centre + rect.height() / 2, mPaint);
Copy the code

Do all of the above, you can achieve a gorgeous circular progress bar function, is not very simple.

Four,

Custom view is widely used in Android development. In order to better master it, it is recommended to systematically learn from custom view drawing process, Canvas, Paint, Path, onLayout(), onMeasure() and onDraw(), and then get started and do more exercises. This is bound to have a good improvement on the custom View! I hope this article is helpful to friends who are learning to customize View.

Said before, to ensure that every custom View beginners can understand, because each line of code will add comments, if not understand the message hit me!!

My wechat account is Jaynm888

Welcome to comment, invite Android programmers to join the wechat communication group, public number reply “add group” or add my wechat pull you into the group