最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Android编程基于自定义View实现绚丽的圆形进度条功能示例
时间:2017-02-27 编辑:简简单单 来源:一聚教程网
本文实例讲述了Android编程基于自定义View实现绚丽的圆形进度条功能。分享给大家供大家参考,具体如下:
本文包含两个组件,首先上效果图:
1.ProgressBarView1(支持拖动):
2.ProgressBarView2(不同进度值显示不同颜色,不支持拖拽):
代码不多,注释也比较详细,全部贴上了:
(一)ProgressBarView1:
代码如下 | 复制代码 |
/** * 自定义绚丽的ProgressBar. */ publicclassProgressBarView1extendsView { /** * 进度条所占用的角度 */ privatestaticfinalintARC_FULL_DEGREE =300; /** * 弧线的宽度 */ privateintSTROKE_WIDTH; /** * 组件的宽,高 */ privateintwidth, height; /** * 进度条最大值和当前进度值 */ privatefloatmax, progress; /** * 是否允许拖动进度条 */ privatebooleandraggingEnabled =false; /** * 绘制弧线的矩形区域 */ privateRectF circleRectF; /** * 绘制弧线的画笔 */ privatePaint progressPaint; /** * 绘制文字的画笔 */ privatePaint textPaint; /** * 绘制当前进度值的画笔 */ privatePaint thumbPaint; /** * 圆弧的半径 */ privateintcircleRadius; /** * 圆弧圆心位置 */ privateintcenterX, centerY; publicProgressBarView1(Context context) { super(context); init(); } publicProgressBarView1(Context context, AttributeSet attrs) { super(context, attrs); init(); } publicProgressBarView1(Context context, AttributeSet attrs,intdefStyleAttr) { super(context, attrs, defStyleAttr); init(); } privatevoidinit() { progressPaint =newPaint(); progressPaint.setAntiAlias(true); textPaint =newPaint(); textPaint.setColor(Color.WHITE); textPaint.setAntiAlias(true); thumbPaint =newPaint(); thumbPaint.setAntiAlias(true); //使用自定义字体 textPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(),"fangz.ttf")); } @Override protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if(width ==0|| height ==0) { width = getWidth(); height = getHeight(); //计算圆弧半径和圆心点 circleRadius = Math.min(width, height) /2; STROKE_WIDTH = circleRadius /12; circleRadius -= STROKE_WIDTH; centerX = width /2; centerY = height /2; //圆弧所在矩形区域 circleRectF =newRectF(); circleRectF.left = centerX - circleRadius; circleRectF.top = centerY - circleRadius; circleRectF.right = centerX + circleRadius; circleRectF.bottom = centerY + circleRadius; } } privateRect textBounds =newRect(); @Override protectedvoidonDraw(Canvas canvas) { super.onDraw(canvas); floatstart =90+ ((360- ARC_FULL_DEGREE) >>1);//进度条起始点 floatsweep1 = ARC_FULL_DEGREE * (progress / max);//进度划过的角度 floatsweep2 = ARC_FULL_DEGREE - sweep1;//剩余的角度 //绘制起始位置小圆形 progressPaint.setColor(Color.WHITE); progressPaint.setStrokeWidth(0); progressPaint.setStyle(Paint.Style.FILL); floatradians = (float) (((360.0f - ARC_FULL_DEGREE) /2) /180* Math.PI); floatstartX = centerX - circleRadius * (float) Math.sin(radians); floatstartY = centerY + circleRadius * (float) Math.cos(radians); canvas.drawCircle(startX, startY, STROKE_WIDTH /2, progressPaint); //绘制进度条 progressPaint.setStrokeWidth(STROKE_WIDTH); progressPaint.setStyle(Paint.Style.STROKE);//设置空心 canvas.drawArc(circleRectF, start, sweep1,false, progressPaint); //绘制进度条背景 progressPaint.setColor(Color.parseColor("#d64444")); canvas.drawArc(circleRectF, start + sweep1, sweep2,false, progressPaint); //绘制结束位置小圆形 progressPaint.setStrokeWidth(0); progressPaint.setStyle(Paint.Style.FILL); floatendX = centerX + circleRadius * (float) Math.sin(radians); floatendY = centerY + circleRadius * (float) Math.cos(radians); canvas.drawCircle(endX, endY, STROKE_WIDTH /2, progressPaint); //上一行文字 textPaint.setTextSize(circleRadius >>1); String text = (int) (100* progress / max) +""; floattextLen = textPaint.measureText(text); //计算文字高度 textPaint.getTextBounds("8",0,1, textBounds); floath1 = textBounds.height(); //% 前面的数字水平居中,适当调整 floatextra = text.startsWith("1") ? -textPaint.measureText("1") /2:0; canvas.drawText(text, centerX - textLen /2+ extra, centerY -30+ h1 /2, textPaint); //百分号 textPaint.setTextSize(circleRadius >>2); canvas.drawText("%", centerX + textLen /2+ extra +5, centerY -30+ h1 /2, textPaint); //下一行文字 textPaint.setTextSize(circleRadius /5); text ="可用内存充足"; textLen = textPaint.measureText(text); textPaint.getTextBounds(text,0, text.length(), textBounds); floath2 = textBounds.height(); canvas.drawText(text, centerX - textLen /2, centerY + h1 /2+ h2, textPaint); //绘制进度位置,也可以直接替换成一张图片 floatprogressRadians = (float) (((360.0f - ARC_FULL_DEGREE) /2+ sweep1) /180* Math.PI); floatthumbX = centerX - circleRadius * (float) Math.sin(progressRadians); floatthumbY = centerY + circleRadius * (float) Math.cos(progressRadians); thumbPaint.setColor(Color.parseColor("#33d64444")); canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH *2.0f, thumbPaint); thumbPaint.setColor(Color.parseColor("#99d64444")); canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH *1.4f, thumbPaint); thumbPaint.setColor(Color.WHITE); canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH *0.8f, thumbPaint); } privatebooleanisDragging =false; @Override publicbooleanonTouchEvent(@NonNullMotionEvent event) { if(!draggingEnabled) { returnsuper.onTouchEvent(event); } //处理拖动事件 floatcurrentX = event.getX(); floatcurrentY = event.getY(); intaction = event.getAction(); switch(action) { caseMotionEvent.ACTION_DOWN: //判断是否在进度条thumb位置 if(checkOnArc(currentX, currentY)) { floatnewProgress = calDegreeByPosition(currentX, currentY) / ARC_FULL_DEGREE * max; setProgressSync(newProgress); isDragging =true; } break; caseMotionEvent.ACTION_MOVE: if(isDragging) { //判断拖动时是否移出去了 if(checkOnArc(currentX, currentY)) { setProgressSync(calDegreeByPosition(currentX, currentY) / ARC_FULL_DEGREE * max); }else{ isDragging =false; } } break; caseMotionEvent.ACTION_UP: isDragging =false; break; } returntrue; } privatefloatcalDistance(floatx1,floaty1,floatx2,floaty2) { return(float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } /** * 判断该点是否在弧线上(附近) */ privatebooleancheckOnArc(floatcurrentX,floatcurrentY) { floatdistance = calDistance(currentX, currentY, centerX, centerY); floatdegree = calDegreeByPosition(currentX, currentY); returndistance > circleRadius - STROKE_WIDTH *5&& distance < circleRadius + STROKE_WIDTH *5 && (degree >= -8&& degree <= ARC_FULL_DEGREE +8); } /** * 根据当前位置,计算出进度条已经转过的角度。 */ privatefloatcalDegreeByPosition(floatcurrentX,floatcurrentY) { floata1 = (float) (Math.atan(1.0f * (centerX - currentX) / (currentY - centerY)) / Math.PI *180); if(currentY < centerY) { a1 +=180; }elseif(currentY > centerY && currentX > centerX) { a1 +=360; } returna1 - (360- ARC_FULL_DEGREE) /2; } publicvoidsetMax(intmax) { this.max = max; invalidate(); } publicvoidsetProgress(floatprogress) { finalfloatvalidProgress = checkProgress(progress); //动画切换进度值 newThread(newRunnable() { @Override publicvoidrun() { floatoldProgress = ProgressBarView1.this.progress; for(inti =1; i <=100; i++) { ProgressBarView1.this.progress = oldProgress + (validProgress - oldProgress) * (1.0f * i /100); postInvalidate(); SystemClock.sleep(20); } } }).start(); } publicvoidsetProgressSync(floatprogress) { this.progress = checkProgress(progress); invalidate(); } //保证progress的值位于[0,max] privatefloatcheckProgress(floatprogress) { if(progress <0) { return0; } returnprogress > max ? max : progress; } publicvoidsetDraggingEnabled(booleandraggingEnabled) { this.draggingEnabled = draggingEnabled; } } |
(二)ProgressBarView2:
代码如下 | 复制代码 |
/** * 自定义绚丽的ProgressBar. */ publicclassProgressBarView2extendsView { /** * 进度条所占用的角度 */ privatestaticfinalintARC_FULL_DEGREE =300; //进度条个数 privatestaticfinalintCOUNT =100; //每个进度条所占用角度 privatestaticfinalfloatARC_EACH_PROGRESS = ARC_FULL_DEGREE *1.0f / (COUNT -1); /** * 弧线细线条的长度 */ privateintARC_LINE_LENGTH; /** * 弧线细线条的宽度 */ privateintARC_LINE_WIDTH; /** * 组件的宽,高 */ privateintwidth, height; /** * 进度条最大值和当前进度值 */ privatefloatmax, progress; /** * 绘制弧线的画笔 */ privatePaint progressPaint; /** * 绘制文字的画笔 */ privatePaint textPaint; /** * 绘制文字背景圆形的画笔 */ privatePaint textBgPaint; /** * 圆弧的半径 */ privateintcircleRadius; /** * 圆弧圆心位置 */ privateintcenterX, centerY; publicProgressBarView2(Context context) { super(context); init(); } publicProgressBarView2(Context context, AttributeSet attrs) { super(context, attrs); init(); } publicProgressBarView2(Context context, AttributeSet attrs,intdefStyleAttr) { super(context, attrs, defStyleAttr); init(); } privatevoidinit() { progressPaint =newPaint(); progressPaint.setAntiAlias(true); textPaint =newPaint(); textPaint.setColor(Color.WHITE); textPaint.setAntiAlias(true); textBgPaint =newPaint(); textBgPaint.setAntiAlias(true); } @Override protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if(width ==0|| height ==0) { width = getWidth(); height = getHeight(); //计算圆弧半径和圆心点 circleRadius = Math.min(width, height) /2; ARC_LINE_LENGTH = circleRadius /6; ARC_LINE_WIDTH = ARC_LINE_LENGTH /8; centerX = width /2; centerY = height /2; } } privateRect textBounds =newRect(); @Override protectedvoidonDraw(Canvas canvas) { super.onDraw(canvas); floatstart = (360- ARC_FULL_DEGREE) >>1;//进度条起始角度 floatsweep1 = ARC_FULL_DEGREE * (progress / max);//进度划过的角度 //绘制进度条 progressPaint.setColor(Color.parseColor(calColor(progress / max,"#ffff0000","#ff00ff00"))); progressPaint.setStrokeWidth(ARC_LINE_WIDTH); floatdrawDegree =1.6f; while(drawDegree <= ARC_FULL_DEGREE) { doublea = (start + drawDegree) /180* Math.PI; floatlineStartX = centerX - circleRadius * (float) Math.sin(a); floatlineStartY = centerY + circleRadius * (float) Math.cos(a); floatlineStopX = lineStartX + ARC_LINE_LENGTH * (float) Math.sin(a); floatlineStopY = lineStartY - ARC_LINE_LENGTH * (float) Math.cos(a); if(drawDegree > sweep1) { //绘制进度条背景 progressPaint.setColor(Color.parseColor("#88aaaaaa")); progressPaint.setStrokeWidth(ARC_LINE_WIDTH >>1); } canvas.drawLine(lineStartX, lineStartY, lineStopX, lineStopY, progressPaint); drawDegree += ARC_EACH_PROGRESS; } //绘制文字背景圆形 textBgPaint.setStyle(Paint.Style.FILL);//设置填充 textBgPaint.setColor(Color.parseColor("#41668b")); canvas.drawCircle(centerX, centerY, (circleRadius - ARC_LINE_LENGTH) *0.8f, textBgPaint); textBgPaint.setStyle(Paint.Style.STROKE);//设置空心 textBgPaint.setStrokeWidth(2); textBgPaint.setColor(Color.parseColor("#aaaaaaaa")); canvas.drawCircle(centerX, centerY, (circleRadius - ARC_LINE_LENGTH) *0.8f, textBgPaint); //上一行文字 textPaint.setTextSize(circleRadius >>1); String text = (int) (100* progress / max) +""; floattextLen = textPaint.measureText(text); //计算文字高度 textPaint.getTextBounds("8",0,1, textBounds); floath1 = textBounds.height(); canvas.drawText(text, centerX - textLen /2, centerY - circleRadius /10+ h1 /2, textPaint); //分 textPaint.setTextSize(circleRadius >>3); textPaint.getTextBounds("分",0,1, textBounds); floath11 = textBounds.height(); canvas.drawText("分", centerX + textLen /2+5, centerY - circleRadius /10+ h1 /2- (h1 - h11), textPaint); //下一行文字 textPaint.setTextSize(circleRadius /6); text ="点击优化"; textLen = textPaint.measureText(text); canvas.drawText(text, centerX - textLen /2, centerY + circleRadius /2.5f, textPaint); } publicvoidsetMax(intmax) { this.max = max; invalidate(); } //动画切换进度值(异步) publicvoidsetProgress(finalfloatprogress) { newThread(newRunnable() { @Override publicvoidrun() { floatoldProgress = ProgressBarView2.this.progress; for(inti =1; i <=100; i++) { ProgressBarView2.this.progress = oldProgress + (progress - oldProgress) * (1.0f * i /100); postInvalidate(); SystemClock.sleep(20); } } }).start(); } //直接设置进度值(同步) publicvoidsetProgressSync(floatprogress) { this.progress = progress; invalidate(); } /** * 计算渐变效果中间的某个颜色值。 * 仅支持 #aarrggbb 模式,例如 #ccc9c9b2 */ publicString calColor(floatfraction, String startValue, String endValue) { intstart_a, start_r, start_g, start_b; intend_a, end_r, end_g, end_b; //start start_a = getIntValue(startValue,1,3); start_r = getIntValue(startValue,3,5); start_g = getIntValue(startValue,5,7); start_b = getIntValue(startValue,7,9); //end end_a = getIntValue(endValue,1,3); end_r = getIntValue(endValue,3,5); end_g = getIntValue(endValue,5,7); end_b = getIntValue(endValue,7,9); return"#"+ getHexString((int) (start_a + fraction * (end_a - start_a))) + getHexString((int) (start_r + fraction * (end_r - start_r))) + getHexString((int) (start_g + fraction * (end_g - start_g))) + getHexString((int) (start_b + fraction * (end_b - start_b))); } //从原始#AARRGGBB颜色值中指定位置截取,并转为int. privateintgetIntValue(String hexValue,intstart,intend) { returnInteger.parseInt(hexValue.substring(start, end),16); } privateString getHexString(intvalue) { String a = Integer.toHexString(value); if(a.length() ==1) { a ="0"+ a; } returna; } } |
相关文章
- Android自定义漂亮的圆形进度条 01-17
- sora软件价格介绍 02-22
- sora官网入口地址一览 02-22
- Sora生成的视频使用教程 02-22
- 《梦幻西游》元宵灯谜线索答案大全2024 02-22
- 《原神》有朋自远方来第一天通关攻略 02-22