溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android繪制圓形百分比加載圈效果

發(fā)布時間:2020-09-04 11:42:18 來源:腳本之家 閱讀:152 作者:mChenys 欄目:移動開發(fā)

先看一組加載效果圖,有點粉粉的加載圈:

Android繪制圓形百分比加載圈效果 Android繪制圓形百分比加載圈效果

自定義這樣的圓形加載圈還是比較簡單的,主要是用到Canvans的繪制文本,繪制圓和繪制圓弧的api:

/**
 * 繪制圓
 * @param cx   圓心x坐標(biāo)
 * @param cy   圓心y坐標(biāo)
 * @param radius 圓的半徑
 * @param paint 畫筆
 */
 public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
 ...
 }


/**
 * 繪制圓弧
 * @param oval    決定圓弧范圍的矩形區(qū)域
 * @param startAngle 開始角度
 * @param sweepAngle 繪制的角度
 * @param useCenter 是否需要連接圓心,true連接,false不連接
 * @param paint   畫筆
 */
 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint) {
  ...
 }


 /**
  * 繪制文本
  * @param text 需要繪制的字符串
  * @param x   繪制文本起點x坐標(biāo),注意文本比較特殊,它的起點是左下角的x坐標(biāo)
  * @param y   繪制文本起點y坐標(biāo),同樣是左下角的y坐標(biāo)
  * @param paint 畫筆
  */
 public void drawText(String text, float x, float y, Paint paint) {
  ...
 }

開始繪圖前需要考慮的以下幾點:

1.獲取控件的寬和高,這個是決定圓的半徑大小的,半徑大小等于寬高的最小值的1/2,為什么是最小值呢?因為這樣就不會受布局文件中寬高屬性不一樣的影響,當(dāng)然我們自己在使用的時候肯定是寬高都是會寫成一樣的,這樣就剛好是一個正方形,繪制出來的圓就剛好在該正方形區(qū)域內(nèi).做了這樣的處理,其他人在用的時候就不用當(dāng)心圓會不會超出控件范圍的情況了.

2.確定圓心的坐標(biāo),有了半徑和圓心坐標(biāo)就可以確定一個圓了,布局中的控件區(qū)域其實都是一個矩形區(qū)域,如果想要繪制出來的圓剛好處于控件的矩形區(qū)域內(nèi)并且和矩形的最短的那條邊相切,那么圓心坐標(biāo)的就是該矩形寬高的1/2,即剛好位于矩形區(qū)域的中心點.

3.繪制圓弧,注意這里的圓弧指的是進度圈,看上面的示例圖是有2種樣式,分別是實心的加載圈和空心加載圈,這個其實就是paint的樣式?jīng)Q定,如果是實心圓,paint設(shè)置為Paint.Style.FILL(填充模式),同時drawArc的useCenter設(shè)置為true;如果是空心圓則paint設(shè)置為Paint.Style.STROKE(線性模式),同時drawArc的useCenter設(shè)置為false即可.值得一提的是繪制空心圓的時候還需要考慮圓弧的寬度,寬度有多大將決定進度圈的厚度.因此在定義空心圓的矩形區(qū)域的時候需要減去進度圈的厚度,否則畫出來的進度圈會超出控件的區(qū)域.

4.繪制文本,需要定位起始點,文本的起始點比較特殊,它是以左下角為起始點的,起點x坐標(biāo)=圓心x坐標(biāo)-文本寬度1/2;起始點y坐標(biāo)=圓心y坐標(biāo)+文本高度1/2;至于文本的寬高獲取可以通過paint的getTextBounds()方法獲取,具體等下看代碼.

ok,直接上代碼,注釋已經(jīng)很詳細了.

圓形加載圈

public class CircleProgressView extends View {
  private int width;//控件寬度
  private int height;//控件高
  private float radius;//半徑
  private float pointX;//圓心x坐標(biāo)
  private float pointY;//圓心y坐標(biāo)
  private int circleBackgroundColor;//背景顏色
  private int circleBackgroundAlpha; //背景透明度
  private int circleRingColor;//進度顏色
  private int progressTextColor;//進度文本的顏色
  private int progressTextSize;//進度文本的字體大小
  private int circleRingWidth; //進度的寬度
  private Paint mPaint;
  private int progress;//進度值
  private boolean isRingStyle;//是否是空心的圓環(huán)進度樣式

  public CircleProgressView(Context context) {
    this(context, null);
  }

  public CircleProgressView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    circleBackgroundColor = Color.WHITE;
    circleRingColor = Color.parseColor("#3A91FF");
    progressTextColor = Color.BLACK;
    circleBackgroundAlpha = 128;
    progressTextSize = 32;
    circleRingWidth = 10;
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setStyle(Paint.Style.FILL);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    width = getMeasuredWidth();
    height = getMeasuredHeight();
    radius = Math.min(width, height) / 2.0f;
    pointX = width / 2.0f;
    pointY = height / 2.0f;
  }

  @Override
  protected void onDraw(Canvas canvas) {
    drawBackground(canvas);
    drawCircleRing(canvas);
    drawProgressText(canvas);
  }

  /**
   * 繪制背景色
   *
   * @param canvas
   */
  private void drawBackground(Canvas canvas) {
    mPaint.setColor(circleBackgroundColor);
    mPaint.setAlpha(circleBackgroundAlpha);
    canvas.drawCircle(pointX, pointY, radius, mPaint);
  }

  /**
   * 繪制圓環(huán)
   *
   * @param canvas
   */
  private void drawCircleRing(Canvas canvas) {
    mPaint.setColor(circleRingColor);
    RectF oval = new RectF();
    if (isRingStyle) {
      mPaint.setStyle(Paint.Style.STROKE);
      mPaint.setStrokeWidth(circleRingWidth);
      mPaint.setStrokeCap(Paint.Cap.ROUND);
      //注意:定義圓環(huán)的矩形區(qū)域是需要考慮圓環(huán)的寬度
      oval.left = circleRingWidth / 2.0f;
      oval.top = height / 2.0f - radius + circleRingWidth / 2.0f;
      oval.right = 2 * radius - circleRingWidth / 2.0f;
      oval.bottom = height / 2.0f + radius - circleRingWidth / 2.0f;
      canvas.drawArc(oval, 0, 360 * progress / 100, false, mPaint);
    } else {
      mPaint.setStyle(Paint.Style.FILL);
      oval.left = 0;
      oval.top = height / 2.0f - radius;
      oval.right = 2 * radius;
      oval.bottom = height / 2.0f + radius;
      canvas.drawArc(oval, 0, 360 * progress / 100, true, mPaint);
    }

  }

  /**
   * 繪制進度文本
   *
   * @param canvas
   */
  private void drawProgressText(Canvas canvas) {
    mPaint.setColor(progressTextColor);
    mPaint.setStyle(Paint.Style.FILL);
    mPaint.setTextSize(progressTextSize);
    Rect textBound = new Rect();
    String text = progress + "%";
    //獲取文本的矩形區(qū)域到textBound中
    mPaint.getTextBounds(text, 0, text.length(), textBound);
    int textWidth = textBound.width();
    int textHeight = textBound.height();
    float x = pointX - textWidth / 2.0f;
    float y = pointY + textHeight / 2.0f;
    canvas.drawText(text, x, y, mPaint);
  }

  /**
   * 更新進度
   *
   * @param progress
   */
  public void setValue(int progress) {
    this.progress = progress;
    invalidate();
  }

  /**
   * 設(shè)置進度圓環(huán)的樣式
   *
   * @param isRing true是空心的圓環(huán),false表示實心的圓環(huán)
   */
  public void setCircleRingStyle(boolean isRing) {
    this.isRingStyle = isRing;
  }

  /**
   * 設(shè)置背景透明度
   *
   * @param alpha 0~255
   */
  public void setCircleBackgroundAlpha(int alpha) {
    this.circleBackgroundAlpha = alpha;
  }

  /**
   * 設(shè)置進度文本的大小
   * @param progressTextSize
   */
  public void setProgressTextSize(int progressTextSize) {
    this.progressTextSize = progressTextSize;
  }

  /**
   * 設(shè)置進度文本的顏色
   * @param progressTextColor
   */
  public void setProgressTextColor(int progressTextColor) {
    this.progressTextColor = progressTextColor;
  }
}

測試類

public class MainActivity extends AppCompatActivity {
  private CircleProgressView mCircleProgressView;
  private int progress;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mCircleProgressView = (CircleProgressView) findViewById(R.id.progressView);
    mCircleProgressView.setCircleRingStyle(false);//實心圓
    HandlerThread thread = new HandlerThread("draw-thread");
    thread.start();
    Handler tHandler = new Handler(thread.getLooper()) {
      @Override
      public void handleMessage(Message msg) {
        runOnUiThread(new Runnable() {
          @Override
          public void run() {
            mCircleProgressView.setValue(progress++);

          }
        });
        if (progress <100) {
          sendEmptyMessageDelayed(0, 100);
        }
      }
    };
    tHandler.sendEmptyMessage(0);
  }
}

XML使用方式

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@color/colorAccent"
 tools:context="mchenys.net.csdn.blog.progressview.MainActivity">


 <mchenys.net.csdn.blog.progressview.CircleProgressView
 android:id="@+id/progressView"
 android:layout_width="100dp"
 android:layout_height="200dp"
 android:layout_centerInParent="true"
 />

</RelativeLayout>

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI