Android自定义圆弧进度条,手动控制进度

一.展示

Android开发中由于需求的不同会遇到各种各样的进度条,本文实现一个自定义手动控制的进度条,先来看一下效果:

  1. 通过按钮控制进度条进度

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@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






你可能感兴趣的:(Android自定义圆弧进度条,手动控制进度)