电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

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

瀏覽:5日期: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
相關文章:
主站蜘蛛池模板: 祝融环境-地源热泵多恒系统高新技术企业,舒适生活环境缔造者! | 金属回收_废铜废铁回收_边角料回收_废不锈钢回收_废旧电缆线回收-广东益夫金属回收公司 | 黄石妇科医院_黄石东方女子医院_黄石东方妇产医院怎么样 | 减速机三参数组合探头|TSM803|壁挂式氧化锆分析仪探头-安徽鹏宸电气有限公司 | 合肥白癜风医院_合肥治疗白癜风医院_合肥看白癜风医院哪家好_合肥华研白癜风医院 | 牛奶检测仪-乳成分分析仪-北京海谊 | 洁净化验室净化工程_成都实验室装修设计施工_四川华锐净化公司 | 一体化污水处理设备_生活污水处理设备_全自动加药装置厂家-明基环保 | 搪瓷搅拌器,搪玻璃搅拌器,搪玻璃冷凝器_厂家-淄博越宏化工设备 | 膜片万向弹性联轴器-冲压铸造模具「沧州昌运模具」 | 上海小程序开发-上海小程序制作公司-上海网站建设-公众号开发运营-软件外包公司-咏熠科技 | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 法钢特种钢材(上海)有限公司 - 耐磨钢板、高强度钢板销售加工 阀门智能定位器_电液动执行器_气动执行机构-赫尔法流体技术(北京)有限公司 | 雾度仪_雾度计_透光率雾度仪价格-三恩时(3nh)光电雾度仪厂家 | 济南品牌包装设计公司_济南VI标志设计公司_山东锐尚文化传播 | 行业分析:提及郑州火车站附近真有 特殊按摩 ?2025实地踩坑指南 新手如何避坑不踩雷 | 杭州标识标牌|文化墙|展厅|导视|户内外广告|发光字|灯箱|铭阳制作公司 - 杭州标识标牌|文化墙|展厅|导视|户内外广告|发光字|灯箱|铭阳制作公司 | 变色龙云 - 打包app_原生app_在线制作平台_短链接_ip查询 | 济南ISO9000认证咨询代理公司,ISO9001认证,CMA实验室认证,ISO/TS16949认证,服务体系认证,资产管理体系认证,SC食品生产许可证- 济南创远企业管理咨询有限公司 郑州电线电缆厂家-防火|低压|低烟无卤电缆-河南明星电缆 | 北京三友信电子科技有限公司-ETC高速自动栏杆机|ETC机柜|激光车辆轮廓测量仪|嵌入式车道控制器 | 针焰试验仪,灼热丝试验仪,漏电起痕试验仪,水平垂直燃烧试验仪 - 苏州亚诺天下仪器有限公司 | 吉林污水处理公司,长春工业污水处理设备,净水设备-长春易洁环保科技有限公司 | AR开发公司_AR增强现实_AR工业_AR巡检|上海集英科技 | 万濠影像仪(万濠投影仪)百科-苏州林泽仪器| 日本SMC气缸接头-速度控制阀-日本三菱伺服电机-苏州禾力自动化科技有限公司 | 电采暖锅炉_超低温空气源热泵_空气源热水器-鑫鲁禹电锅炉空气能热泵厂家 | 北京工业设计公司-产品外观设计-产品设计公司-千策良品工业设计 北京翻译公司-专业合同翻译-医学标书翻译收费标准-慕迪灵 | 水厂自动化-水厂控制系统-泵站自动化|控制系统-闸门自动化控制-济南华通中控科技有限公司 | 执业药师报名时间,报考条件,考试时间-首页入口 | 回转窑-水泥|石灰|冶金-巩义市瑞光金属制品有限责任公司 | 无菌检查集菌仪,微生物限度仪器-苏州长留仪器百科 | 多米诺-多米诺世界纪录团队-多米诺世界-多米诺团队培训-多米诺公关活动-多米诺创意广告-多米诺大型表演-多米诺专业赛事 | 特材真空腔体_哈氏合金/镍基合金/纯镍腔体-无锡国德机械制造有限公司 | 高效节能电机_伺服主轴电机_铜转子电机_交流感应伺服电机_图片_型号_江苏智马科技有限公司 | 医养体检包_公卫随访箱_慢病随访包_家签随访包_随访一体机-济南易享医疗科技有限公司 | 不锈钢酒柜|恒温酒柜|酒柜定制|酒窖定制-上海啸瑞实业有限公司 | 除尘器布袋骨架,除尘器滤袋,除尘器骨架,电磁脉冲阀膜片,卸灰阀,螺旋输送机-泊头市天润环保机械设备有限公司 | 成都装修公司-成都装修设计公司推荐-成都朗煜装饰公司 | 考勤系统_人事考勤管理系统_本地部署BS考勤系统_考勤软件_天时考勤管理专家 | 板框压滤机-隔膜压滤机-厢式压滤机生产厂家-禹州市君工机械设备有限公司 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 |