成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Android自定義控件實現圓形進度CircleProgressBar

瀏覽:2日期:2022-09-24 10:55:58

近日有朋友問我有沒有如下圖效果的開源控件

Android自定義控件實現圓形進度CircleProgressBar

相信大家無論是用IOS還是Android,都對這種效果不陌生,很多主流APP都會有這樣或類似的效果,之前也打算研究一下這類控件的代碼,苦于一直不知道應該怎么搜索這種效果(就是關鍵詞)或者所搜的結果不是自己想要的,所以就一直擱置了下來。

正好朋友需要這種效果,所以就忙里偷閑寫了一個類似的、更加常見和適用范圍更多的控件,效果如下圖所示:

Android自定義控件實現圓形進度CircleProgressBar

自定義上圖所示效果的控件時,其實就是用Canvas繪制不同效果,比如漸變圓弧背景、圓周白色分割線、中間文字等,這篇博客也根據繪制的順序依次闡述。

1.自定義CircleProgressBar,繼承View,并實現響應的構造函數

代碼如下:

/** * Created by WangChunLei on 2016.1.16 * E-mail:wcl_android@163.com */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(); }}

其中init方法是對相關畫筆進行初始化的方法,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(); 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.測量控件的寬高-onMeasure

onMeasure是自定義控件的第一步,目的就是測量得到該控件應該占有的寬高尺寸。其中onMeasure方法的代碼如下:

@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)); }

貼上onMeasure的代碼后,大家估計是很少見過測量過程這么簡單的onMeasure,不要介意,有興趣的同僚們可以細化一下這個測量過程,對不同的測量模式分別進行處理和測量,讓控件適配效果更好更完善!

onMeasure方法中,分別獲取期望的寬度和高度,并取其中較小的尺寸作為該控件的寬和高。

3.依次繪制不同的控件組成部分。

因為控件是直接繼承自View,所以不需要再處理onLayout方法,這也是自定義View的難度遠小于自定義ViewGroup的原因,但繼承ViewGroup也并不一定要重寫onMeasure。 要實現如圖所示的效果,需要分以下步驟依次實現

(1)繪制灰色空心圓環 (2)繪制顏色漸變的圓環 (3)繪制圓環上分割的白色線條 (4)繪制百分比文字等。

繪制過程過,后繪制的內容如果與之前繪制的內容存在交集,則后繪制的內容會覆蓋掉之前繪制的內容。

按照上述步驟依次介紹

在繪制過程中,會產生以下成員變量,下文中會用到:

/*圓弧線寬*/ private float circleBorderWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()); /*內邊距*/ private float circlePadding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()); /*字體大小*/ private float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 50, getResources().getDisplayMetrics()); /*繪制圓周的畫筆*/ private Paint backCirclePaint; /*繪制圓周白色分割線的畫筆*/ private Paint linePaint; /*繪制文字的畫筆*/ private Paint textPaint; /*百分比*/ private int percent = 0; /*漸變圓周顏色數組*/ private int[] gradientColorArray = new int[]{Color.GREEN, Color.parseColor('#fe751a'), Color.parseColor('#13be23'), Color.GREEN}; private Paint gradientCirclePaint;

3.1繪制灰色空心圓環

代碼如下:

//1.繪制灰色背景圓環 canvas.drawArc( new RectF(circlePadding * 2, circlePadding * 2, getMeasuredWidth() - circlePadding * 2, getMeasuredHeight() - circlePadding * 2), -90, 360, false, backCirclePaint);

其中,-90為繪制圓弧的起始角度,360是圓弧繪制的角度,即sweepAngle.

3.2繪制顏色漸變的圓環

//2.繪制顏色漸變圓環 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.0) * 360, false, gradientCirclePaint);

其中,linearGradient是Paint的shadow,是為了圓弧的顏色漸變效果的而需要設置的,日常開發中應用頻率不高,但的確是可以實現非常理想的顏色漸變效果。

3.3繪制圓環上分割的白色線條

繪制圓弧上的白色線條時,需要進行一些簡單的運算,比如線條的起始坐標startX,startY和線條的終止坐標stopX,stopY等,利用簡單的三角函數還是很容易去計算出來的。 效果中,將圓弧使用白色線條平分成100分,每一個的階級為1,可以滿足int類型的百分比與效果圖比例的一致。

//半徑float radius = (getMeasuredWidth() - circlePadding * 3) / 2; //X軸中點坐標 int centerX = getMeasuredWidth() / 2; //3.繪制100份線段,切分空心圓弧 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繪制百分比文字等

最后繪制百分比文字。 繪制文字時,為了保持文字的中心點和圓弧的原點一致,需要先測量得到要顯示文字的寬度和高度,然后再進行一些簡單的運算,原理不再贅述,相信大家數學一定都比我好。

//4.繪制文字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);

最后,暴漏一個公共的方法供改變顯示的百分比,代碼如下:

/** * 設置百分比 * * @param percent */ public void setPercent(int percent) { if (percent < 0) { percent = 0; } else if (percent > 100) { percent = 100; } this.percent = percent; invalidate(); }

至此,所有繪制過程簡述完畢,130行代碼就能實現很炫酷的效果有木有?

最后,貼上項目完整代碼,供懶得看實現過程的同僚們使用,O(∩_∩)O哈哈~

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 on 2016.1.16 * e-mail:wcl_android@163.com */public class GradientProgressBar extends View { /*圓弧線寬*/ private float circleBorderWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()); /*內邊距*/ private float circlePadding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()); /*字體大小*/ private float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 50, getResources().getDisplayMetrics()); /*繪制圓周的畫筆*/ private Paint backCirclePaint; /*繪制圓周白色分割線的畫筆*/ private Paint linePaint; /*繪制文字的畫筆*/ private Paint textPaint; /*百分比*/ private int percent = 0; /*漸變圓周顏色數組*/ private int[] gradientColorArray = new int[]{Color.GREEN, Color.parseColor('#fe751a'), Color.parseColor('#13be23'), Color.GREEN}; 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(); 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); } @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)); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //1.繪制灰色背景圓環 canvas.drawArc( new RectF(circlePadding * 2, circlePadding * 2, getMeasuredWidth() - circlePadding * 2, getMeasuredHeight() - circlePadding * 2), -90, 360, false, backCirclePaint); //2.繪制顏色漸變圓環 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.0) * 360, false, gradientCirclePaint); //半徑 float radius = (getMeasuredWidth() - circlePadding * 3) / 2; //X軸中點坐標 int centerX = getMeasuredWidth() / 2; //3.繪制100份線段,切分空心圓弧 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); } //4.繪制文字 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); } /** * 設置百分比 * * @param percent */ public void setPercent(int percent) { if (percent < 0) { percent = 0; } else if (percent > 100) { percent = 100; } this.percent = percent; invalidate(); }}

最后,貼上自定義控件代碼(自定義控件、Activity,布局文件)下載地址: Android圓形進度CircleProgressBar

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Android
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
久久久精品一品道一区| 欧美国产在线观看| 日韩免费视频一区| 日韩和的一区二区| 亚洲国产综合在线看不卡| 中文字幕免费不卡| 欧美在线视屏| 国产欧美一区二区在线观看| 91网页版在线| 久久人人97超碰com| 成人av在线观| 精品欧美一区二区三区精品久久| 国产综合色视频| 欧美色手机在线观看| 日日夜夜精品视频免费| 国产精品久久777777毛茸茸| 亚洲情趣在线观看| 激情亚洲网站| 自拍偷拍亚洲欧美日韩| 欧美特黄一级| 国产精品久久久久桃色tv| 欧美日韩一区二区高清| 中文字幕二三区不卡| 欧美国产另类| 国产精品乱码一区二区三区软件| 91蜜桃网址入口| 久久久亚洲欧洲日产国码αv| 99久久久久久99| 久久久久久一二三区| 成人h版在线观看| 2022国产精品视频| 91视视频在线直接观看在线看网页在线看| 久久综合久久综合亚洲| 97精品国产露脸对白| 亚洲国产精品国自产拍av| 欧美精品入口| 国产精品成人免费精品自在线观看| 伊人蜜桃色噜噜激情综合| 亚洲精品老司机| 久久国产精品久久精品国产| 青青草97国产精品免费观看| 欧美日韩高清一区二区三区| 国产成人精品三级| 精品91自产拍在线观看一区| 欧美伊人久久| 亚洲青青青在线视频| 久久精品人人| 美女网站视频久久| 在线电影院国产精品| 91一区一区三区| 亚洲欧美一区二区三区极速播放| 久久久精品日韩| 国产在线麻豆精品观看| 久久女同精品一区二区| 国产精品成人一区二区网站软件| 综合欧美亚洲日本| 欧美中日韩免费视频| 久久精品噜噜噜成人av农村| 日韩一级在线观看| 欧美.www| 樱花草国产18久久久久| 色呦呦国产精品| 国产91精品一区二区麻豆亚洲| 欧美大肚乱孕交hd孕妇| 国产精品99一区二区| 亚洲国产婷婷综合在线精品| 欧美三级午夜理伦三级中视频| 成人免费视频caoporn| 中文字幕一区二区三区视频| 麻豆精品视频| 国产在线精品一区二区夜色| 国产欧美日韩在线视频| 亚洲欧美卡通另类91av | 日本一区二区三区国色天香 | 日韩avvvv在线播放| 日韩一二在线观看| 国产精品对白刺激久久久| 午夜精品福利一区二区三区av| 欧美精选在线播放| 欧美色123| 午夜精品一区二区三区免费视频| 欧美一区二区三级| 激情欧美一区| 国产最新精品精品你懂的| 国产欧美一区二区在线| 久久精品中文字幕一区二区三区| 国产精品18久久久久久久网站| 国产精品麻豆视频| 老司机精品视频网站| 成人午夜激情片| 夜夜嗨av一区二区三区中文字幕 | 一区二区三区四区国产| 国产一区二区三区四区在线观看| 欧美激情在线一区二区三区| 免费在线观看一区二区| 国产成人午夜精品5599| 亚洲色图在线视频| 欧美精品久久一区| 国内自拍一区| 国内外成人在线| 一区二区三区在线免费| 精品久久国产老人久久综合| 国产日韩一区二区三区| a美女胸又www黄视频久久| 午夜精品aaa| ww久久中文字幕| 色先锋资源久久综合| 欧美人与禽性xxxxx杂性| 日韩黄色一级片| 国产精品女同互慰在线看| 欧美四级电影网| 亚洲大胆女人| 成人精品小蝌蚪| 亚洲一区二区视频在线| 91精品国产综合久久香蕉的特点| 亚洲午夜精品国产| 黄色精品一二区| 亚洲激情六月丁香| 精品国产电影一区二区| 欧美在线视频日韩| 一本色道婷婷久久欧美| caoporn国产一区二区| 日韩精品国产精品| 国产精品久久久久久久久久免费看| 欧美群妇大交群中文字幕| 亚洲激情啪啪| 不卡视频一二三| 美女视频一区二区三区| 成人免费在线播放视频| 欧美一级黄色录像| 色婷婷综合五月| 亚洲国产99| 91在线无精精品入口| 久久99国产精品免费网站| 亚洲综合精品自拍| 国产精品视频你懂的| 91精品国产欧美一区二区18| 久久经典综合| 亚洲欧洲综合| 91亚洲精华国产精华精华液| 国产精品一线二线三线| 日本va欧美va欧美va精品| 亚洲天堂中文字幕| 久久久久久久免费视频了| 欧美三级中文字幕在线观看| 国产欧美日本| 欧美午夜欧美| 99久久er热在这里只有精品66| 狠狠色狠狠色综合日日91app| 视频在线观看国产精品| 一区二区三区**美女毛片| 亚洲视频免费观看| 国产精品天干天干在线综合| 久久美女高清视频| 精品日韩在线一区| 91精品国产综合久久蜜臀| 欧美日韩一级大片网址| 欧洲精品视频在线观看| 另类激情亚洲| 亚洲一区二区高清视频| 激情一区二区| 国内视频精品| 欧美精品自拍| 你懂的视频一区二区| 99久久精品久久久久久清纯| 成年人国产精品| 成人a级免费电影| 成人国产一区二区三区精品| 成人免费毛片嘿嘿连载视频| 国产乱码精品一区二区三区五月婷| 麻豆91免费看| 奇米精品一区二区三区四区| 亚洲国产精品久久不卡毛片| 亚洲人成精品久久久久| 最新不卡av在线| 亚洲天堂中文字幕| 国产精品第一页第二页第三页| 国产欧美精品在线观看| 久久色在线视频| 久久蜜桃一区二区| 制服丝袜亚洲网站| 在线综合亚洲欧美在线视频| 欧美人xxxx| 欧美一区欧美二区| 日韩手机在线导航| 日韩欧美中文字幕制服| 精品黑人一区二区三区久久| 久久综合色播五月| 国产日本亚洲高清| 中文字幕精品一区二区精品绿巨人 | 精品国产第一区二区三区观看体验 | 欧美一区免费| 欧美视频四区| 一本不卡影院| 久久综合一区二区三区| 在线视频一区二区免费| 91麻豆精品国产自产在线| 日韩一级片在线播放| 另类av一区二区| 欧美性猛交xxxx黑人交|