赞
踩
Android开发中由于需求的不同会遇到各种各样的进度条,本文实现一个自定义手动控制的进度条,先来看一下效果:
2.通过滑动进度条上的按钮控制进度
如上展示效果可见,圆弧所跨弧度为270,其中可将绘制分为6个部分:
1.代码实现中各个属性的定义以及其作用:
- /**
- * 进度条所占用的角度
- */
- private static final int ARC_FULL_DEGREE = 270;
- /**
- * 弧线的宽度
- */
- private int STROKE_WIDTH;
- /**
- * 组件的宽,高
- */
- private int width, height,sWidth,sHeight;
-
- /**
- * 进度条最大值和当前进度值
- */
- private float max, progress;
- /**
- * 是否允许拖动进度条
- */
- private boolean draggingEnabled = false;
- /**
- * 绘制弧线的矩形区域
- */
- private RectF circleRectF,zhizhenRectF;
- /**
- * 绘制弧线的画笔
- */
- private Paint progressPaint;
- /**
- * 绘制文字的画笔
- */
- private Paint textPaint;
- /**
- * 绘制当前进度值的画笔
- */
- private Paint thumbPaint;
- /**
- * 圆弧的半径
- */
- private int circleRadius;
- /**
- * 圆弧圆心位置
- */
- private int centerX, centerY;
- private int upBtCenterX,upBtCenterY,downBtCenterx,downBtCenterY;//控制按钮的坐标
- private Bitmap zhizhen;
- private Matrix matrix;//矩阵--控制指针图片的动画
- /**
- * 指针圆心
- */
- private float circleRectFCenterWidth;
- private float circleRectFCenterHeight;
- /**
- * 圆弧上渐变色的颜色值
- */
- private final int[] colors = {Color.parseColor("#FFF68F"),Color.parseColor("#FFE700")
- ,Color.parseColor("#FFD700"),Color.parseColor("#FFC700")
- ,Color.parseColor("#FFB700"),Color.parseColor("#FFA700")
- ,Color.parseColor("#FF9700"),Color.parseColor("#FF7F00")};

2.圆弧,控制按钮,以及其他显示的绘制:
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- Log.e("ondraw", "测试2");
-
- float start = 90 + ((360 - ARC_FULL_DEGREE) >> 1); //进度条起始点
- float sweep1 = ARC_FULL_DEGREE * (progress / max); //进度划过的角度
- float sweep2 = ARC_FULL_DEGREE - sweep1; //剩余的角度
- float progressRadians = (float) (((360.0f - ARC_FULL_DEGREE) / 2 + sweep1) / 180 * Math.PI);
- float thumbX = centerX - circleRadius * (float) Math.sin(progressRadians);
- float thumbY = centerY + circleRadius * (float) Math.cos(progressRadians);
-
- //绘制起始位置小圆形
- progressPaint.setColor(Color.WHITE);
- progressPaint.setStrokeWidth(0);
- progressPaint.setStyle(Paint.Style.FILL);
- float radians = (float) (((360.0f - ARC_FULL_DEGREE) / 2) / 180 * Math.PI);
- float startX = centerX - circleRadius * (float) Math.sin(radians);
- float startY = centerY + circleRadius * (float) Math.cos(radians);
- System.out.println("startX=" + startX + ";startY="+ startY);
- canvas.drawCircle(startX, startY, STROKE_WIDTH / 2, progressPaint);
-
- //绘制控制进度减按钮
- buttonRadius = circleRadius/8;
- downBtCenterx=(int) (startX+buttonRadius);
- downBtCenterY=(int) (startY+4*buttonRadius);
- progressPaint.setColor(Color.parseColor("#8800FFFF"));
- canvas.drawCircle(startX+buttonRadius, startY+4*buttonRadius, buttonRadius, progressPaint);
- progressPaint.setColor(Color.parseColor("#F0FFFF"));
- progressPaint.setStrokeWidth(5);
- canvas.drawLine(startX+buttonRadius-buttonRadius*3/4, startY+4*buttonRadius, startX+buttonRadius+buttonRadius*3/4, startY+4*buttonRadius, progressPaint);
- Log.e("onDraw", "测试-画圆");
- //绘制进度条
- for(int i=0;i<colors.length;i++){
- position[i]=(float)(0.37+i*(progressRadians*100/360)/colors.length);
- }
- progressPaint.setStrokeWidth(STROKE_WIDTH);
- progressPaint.setStyle(Paint.Style.STROKE);//设置空心
- LinearGradient linearGradient = new LinearGradient(startX, startY, thumbX, thumbY, colors, position, TileMode.CLAMP);
- progressPaint.setShader(linearGradient);
- canvas.drawArc(circleRectF, start, sweep1, false, progressPaint);
- //绘制进度条背景
- linearGradient=null;
- progressPaint.setShader(null);
- progressPaint.setColor(Color.parseColor("#d64444"));
- canvas.drawArc(circleRectF, start + sweep1, sweep2, false, progressPaint);
- Log.e("onDraw", "测试-画进度条");
-
- //绘制结束位置小圆形
- progressPaint.setStrokeWidth(0);
- progressPaint.setStyle(Paint.Style.FILL);
- float endX = centerX + circleRadius * (float) Math.sin(radians);
- float endY = centerY + circleRadius * (float) Math.cos(radians);
- canvas.drawCircle(endX, endY, STROKE_WIDTH / 2, progressPaint);
- Log.e("onDraw", "测试-画按钮");
-
- // 绘制进度加按钮
- upBtCenterX=(int) (endX-buttonRadius);
- upBtCenterY=(int) (endY+4*buttonRadius);
- progressPaint.setColor(Color.parseColor("#8800FFFF"));
- canvas.drawCircle(endX-buttonRadius, endY+4*buttonRadius, buttonRadius, progressPaint);
- progressPaint.setColor(Color.parseColor("#F0FFFF"));
- progressPaint.setStrokeWidth(5);
- canvas.drawLine(endX-buttonRadius-buttonRadius*3/4, endY+4*buttonRadius, endX-buttonRadius+buttonRadius*3/4, endY+4*buttonRadius, progressPaint);
- canvas.drawLine(endX-buttonRadius, endY+4*buttonRadius-buttonRadius*3/4, endX-buttonRadius, endY+4*buttonRadius+buttonRadius*3/4, progressPaint);
- progressPaint.setColor(Color.WHITE);
- //画出指针动画
- matrix.reset();
- matrix.postTranslate(circleRectFCenterWidth-width/2, circleRectFCenterHeight-height/2);
- matrix.preRotate(40,width/2,height/2);
- matrix.postRotate((float)(progressRadians*(180/Math.PI)),circleRectFCenterWidth, circleRectFCenterHeight);
- System.out.println("宽="+ zhizhen.getWidth() + " 高=" + zhizhen.getHeight());
- canvas.drawBitmap(zhizhen, matrix, progressPaint);
- canvas.drawCircle(circleRectFCenterWidth, circleRectFCenterHeight, (float) (0.36*width), progressPaint);
-
- //上一行文字
- textPaint.setTextSize(circleRadius >> 1);
- String text = (int) (100 * progress / max) + "";
- float textLen = textPaint.measureText(text);
- //计算文字高度
- textPaint.getTextBounds("8", 0, 1, textBounds);
- float h1 = textBounds.height();
- //% 前面的数字水平居中,适当调整
- float extra = text.startsWith("1") ? -textPaint.measureText("1") / 2 : 0;
- canvas.drawText(text, centerX - textLen / 2 + extra, centerY - 30 + h1 / 2, textPaint);
-
- //绘制进度条上的按钮
- 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);
- Log.e("onDraw", "测试-完成");
- System.out.println("进度值progress="+progress);
- }

3.点击事件的实现:
- @Override
- public boolean onTouchEvent(@NonNull MotionEvent event) {
- if (!draggingEnabled) {
- return super.onTouchEvent(event);
- }
- Log.e("onTouchEvent", "测试3");
-
- //处理拖动事件
- float currentX = event.getX();
- float currentY = event.getY();
-
- int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- //判断是否在进度条thumb位置
- if (checkOnArc(currentX, currentY)) {
- newProgress = calDegreeByPosition(currentX, currentY) / ARC_FULL_DEGREE * max;
- setProgressSync(newProgress);
- isDragging = true;
- } else if(checkOnButtonUp(currentX, currentY)){
- // TODO Auto-generated method stub
- setProgress(progress+10);
- isDragging = false;
- }else if(checkOnButtonDwon(currentX, currentY)){
- setProgress(progress-10);
- isDragging = false;
- }
- break;
- case MotionEvent.ACTION_MOVE:
- if (isDragging) {
- //判断拖动时是否移出去了
- if (checkOnArc(currentX, currentY)) {
- setProgressSync(calDegreeByPosition(currentX, currentY) / ARC_FULL_DEGREE * max);
- } else {
- isDragging = false;
- }
- }
- break;
- case MotionEvent.ACTION_UP:
- isDragging = false;
- break;
- }
- return true;
- }

点击事件中,分别对ACTION_DOWN事件,ACTION_UP事件和ACTION_MOVE事件进行了处理,当控制进度条的时候,需要判断点击事件是否在控制区域,所以,此时需要设置点击响应区域,该区域在圆弧上,圆弧控制上的按钮和控制按钮可适当扩大,防止点击时候点击不准确从而导致不能触发点击事件。除此之外,还需要注意在这几个部分扩大点击区域时,防止其中多个点击区域相交,导致点击该区域时,触发两个部分的点击事件。此处列出圆弧上点击区域的控制实现:
- /**
- * 判断该点是否在弧线上(附近)
- */
- private boolean checkOnArc(float currentX, float currentY) {
- float distance = calDistance(currentX, currentY, centerX, centerY);
- float degree = calDegreeByPosition(currentX, currentY);
- return distance > circleRadius - STROKE_WIDTH * 5 && distance < circleRadius + STROKE_WIDTH * 5
- && (degree >= -8 && degree <= ARC_FULL_DEGREE + 8);
- }
https://download.csdn.net/download/lanhao21/10308826
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。