先看一組加載效果圖,有點粉粉的加載圈:
創(chuàng)新互聯(lián)專注于七臺河企業(yè)網(wǎng)站建設(shè),成都響應式網(wǎng)站建設(shè)公司,成都做商城網(wǎng)站。七臺河網(wǎng)站建設(shè)公司,為七臺河等地區(qū)提供建站服務(wù)。全流程按需求定制制作,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
自定義這樣的圓形加載圈還是比較簡單的,主要是用到Canvans的繪制文本,繪制圓和繪制圓弧的api:
/** * 繪制圓 * @param cx 圓心x坐標 * @param cy 圓心y坐標 * @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坐標,注意文本比較特殊,它的起點是左下角的x坐標 * @param y 繪制文本起點y坐標,同樣是左下角的y坐標 * @param paint 畫筆 */ public void drawText(String text, float x, float y, Paint paint) { ... }
開始繪圖前需要考慮的以下幾點:
1.獲取控件的寬和高,這個是決定圓的半徑大小的,半徑大小等于寬高的最小值的1/2,為什么是最小值呢?因為這樣就不會受布局文件中寬高屬性不一樣的影響,當然我們自己在使用的時候肯定是寬高都是會寫成一樣的,這樣就剛好是一個正方形,繪制出來的圓就剛好在該正方形區(qū)域內(nèi).做了這樣的處理,其他人在用的時候就不用當心圓會不會超出控件范圍的情況了.
2.確定圓心的坐標,有了半徑和圓心坐標就可以確定一個圓了,布局中的控件區(qū)域其實都是一個矩形區(qū)域,如果想要繪制出來的圓剛好處于控件的矩形區(qū)域內(nèi)并且和矩形的最短的那條邊相切,那么圓心坐標的就是該矩形寬高的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坐標=圓心x坐標-文本寬度1/2;起始點y坐標=圓心y坐標+文本高度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坐標 private float pointY;//圓心y坐標 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"?>
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。