Android繪制圓形百分比加載圈效果
先看一組加載效果圖,有點(diǎn)粉粉的加載圈:
自定義這樣的圓形加載圈還是比較簡單的,主要是用到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 繪制文本起點(diǎn)x坐標(biāo),注意文本比較特殊,它的起點(diǎn)是左下角的x坐標(biāo) * @param y 繪制文本起點(diǎn)y坐標(biāo),同樣是左下角的y坐標(biāo) * @param paint 畫筆 */ public void drawText(String text, float x, float y, Paint paint) { ... }
開始繪圖前需要考慮的以下幾點(diǎn):
1.獲取控件的寬和高,這個(gè)是決定圓的半徑大小的,半徑大小等于寬高的最小值的1/2,為什么是最小值呢?因?yàn)檫@樣就不會(huì)受布局文件中寬高屬性不一樣的影響,當(dāng)然我們自己在使用的時(shí)候肯定是寬高都是會(huì)寫成一樣的,這樣就剛好是一個(gè)正方形,繪制出來的圓就剛好在該正方形區(qū)域內(nèi).做了這樣的處理,其他人在用的時(shí)候就不用當(dāng)心圓會(huì)不會(huì)超出控件范圍的情況了.
2.確定圓心的坐標(biāo),有了半徑和圓心坐標(biāo)就可以確定一個(gè)圓了,布局中的控件區(qū)域其實(shí)都是一個(gè)矩形區(qū)域,如果想要繪制出來的圓剛好處于控件的矩形區(qū)域內(nèi)并且和矩形的最短的那條邊相切,那么圓心坐標(biāo)的就是該矩形寬高的1/2,即剛好位于矩形區(qū)域的中心點(diǎn).
3.繪制圓弧,注意這里的圓弧指的是進(jìn)度圈,看上面的示例圖是有2種樣式,分別是實(shí)心的加載圈和空心加載圈,這個(gè)其實(shí)就是paint的樣式?jīng)Q定,如果是實(shí)心圓,paint設(shè)置為Paint.Style.FILL(填充模式),同時(shí)drawArc的useCenter設(shè)置為true;如果是空心圓則paint設(shè)置為Paint.Style.STROKE(線性模式),同時(shí)drawArc的useCenter設(shè)置為false即可.值得一提的是繪制空心圓的時(shí)候還需要考慮圓弧的寬度,寬度有多大將決定進(jìn)度圈的厚度.因此在定義空心圓的矩形區(qū)域的時(shí)候需要減去進(jìn)度圈的厚度,否則畫出來的進(jìn)度圈會(huì)超出控件的區(qū)域.
4.繪制文本,需要定位起始點(diǎn),文本的起始點(diǎn)比較特殊,它是以左下角為起始點(diǎn)的,起點(diǎn)x坐標(biāo)=圓心x坐標(biāo)-文本寬度1/2;起始點(diǎn)y坐標(biāo)=圓心y坐標(biāo)+文本高度1/2;至于文本的寬高獲取可以通過paint的getTextBounds()方法獲取,具體等下看代碼.
ok,直接上代碼,注釋已經(jīng)很詳細(xì)了.
圓形加載圈
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;//進(jìn)度顏色 private int progressTextColor;//進(jìn)度文本的顏色 private int progressTextSize;//進(jìn)度文本的字體大小 private int circleRingWidth; //進(jìn)度的寬度 private Paint mPaint; private int progress;//進(jìn)度值 private boolean isRingStyle;//是否是空心的圓環(huán)進(jì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); } } /** * 繪制進(jìn)度文本 * * @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); } /** * 更新進(jìn)度 * * @param progress */ public void setValue(int progress) { this.progress = progress; invalidate(); } /** * 設(shè)置進(jìn)度圓環(huán)的樣式 * * @param isRing true是空心的圓環(huán),false表示實(shí)心的圓環(huán) */ public void setCircleRingStyle(boolean isRing) { this.isRingStyle = isRing; } /** * 設(shè)置背景透明度 * * @param alpha 0~255 */ public void setCircleBackgroundAlpha(int alpha) { this.circleBackgroundAlpha = alpha; } /** * 設(shè)置進(jìn)度文本的大小 * @param progressTextSize */ public void setProgressTextSize(int progressTextSize) { this.progressTextSize = progressTextSize; } /** * 設(shè)置進(jìn)度文本的顏色 * @param progressTextColor */ public void setProgressTextColor(int progressTextColor) { this.progressTextColor = progressTextColor; } }
測(cè)試類
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);//實(shí)心圓 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)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android 實(shí)現(xiàn)圓角圖片的簡單實(shí)例
這篇文章主要介紹了Android 實(shí)現(xiàn)圓角圖片的簡單實(shí)例的相關(guān)資料,Android 圓角圖片的實(shí)現(xiàn)形式,包括用第三方、也有系統(tǒng),需要的朋友可以參考下2017-07-07Android編程顯示網(wǎng)絡(luò)上的圖片實(shí)例詳解
這篇文章主要介紹了Android編程顯示網(wǎng)絡(luò)上的圖片,結(jié)合實(shí)例形式詳細(xì)分析了Android顯示網(wǎng)絡(luò)圖片的流程與具體操作技巧,需要的朋友可以參考下2016-10-10Android 圓角 ImageView類可設(shè)置弧度(代碼簡單)
這篇文章主要介紹了Android 圓角 ImageView類可設(shè)置弧度 的相關(guān)資料,需要的朋友可以參考下2016-03-03android TextView 設(shè)置和取消刪除線的兩種方法
這篇文章主要介紹了android TextView 設(shè)置和取消刪除線的兩種方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03Android源碼解析onResume方法中獲取不到View寬高
這篇文章主要為大家介紹了Android源碼解析onResume方法中獲取不到View寬高示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02在Android中查看當(dāng)前Activity是否銷毀的操作
這篇文章主要介紹了在Android中查看當(dāng)前Activity是否銷毀的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-03-03