记一次 中间带字的进度条 效果

先看效果图

 

 

 

1.自定义的控件

public class CircleBarView extends View {
    private OnAnimationListener onAnimationListener;
    private TextView textView;
    private float sweepAngle;//圆弧经过的角度
    private Paint rPaint;//绘制矩形的画笔
    private Paint progressPaint;//绘制圆弧的画笔
    CircleBarAnim anim;

    private Paint bgPaint;//绘制背景圆弧的画笔

    private float progressNum;//可以更新的进度条数值
    private float maxNum;//进度条最大值

    private float progressSweepAngle;//进度条圆弧扫过的角度
    private float startAngle;//背景圆弧的起始角度

    private RectF mRectF;//绘制圆弧的矩形区域

    private float barWidth;//圆弧进度条宽度
    private int defaultSize;//自定义View默认的宽高

    private int progressColor;//进度条圆弧颜色
    private int bgColor;//背景圆弧颜色


    public CircleBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        rPaint = new Paint();
        rPaint.setStyle(Paint.Style.STROKE);//只描边,不填充
        rPaint.setColor(Color.RED);

        progressPaint = new Paint();
        progressPaint.setStyle(Paint.Style.STROKE);//只描边,不填充
        progressPaint.setColor(Color.BLUE);
        progressPaint.setAntiAlias(true);//设置抗锯齿

        anim = new CircleBarAnim();

        progressPaint = new Paint();
        progressPaint.setStyle(Paint.Style.STROKE);//只描边,不填充
        progressPaint.setColor(Color.GREEN);
        progressPaint.setAntiAlias(true);//设置抗锯齿
        progressPaint.setStrokeWidth(15);//随便设置一个画笔宽度,看看效果就好,之后会通过attr自定义属性进行设置

        bgPaint = new Paint();
        bgPaint.setStyle(Paint.Style.STROKE);//只描边,不填充
        bgPaint.setColor(Color.GRAY);
        bgPaint.setAntiAlias(true);//设置抗锯齿
        bgPaint.setStrokeWidth(15);

        progressNum = 0;
        maxNum = 100;//也是随便设的

        startAngle = 0;
        sweepAngle = 360;

        defaultSize = dip2px(context, 100);
        barWidth = dip2px(context, 10);
        mRectF = new RectF();

        progressPaint.setStrokeWidth(barWidth);

        bgPaint.setStrokeWidth(barWidth);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleBarView);

        progressColor = typedArray.getColor(R.styleable.CircleBarView_progress_color, Color.GREEN);//默认为绿色
        bgColor = typedArray.getColor(R.styleable.CircleBarView_bg_color, Color.GRAY);//默认为灰色
        startAngle = typedArray.getFloat(R.styleable.CircleBarView_start_angle, 0);//默认为0
        sweepAngle = typedArray.getFloat(R.styleable.CircleBarView_sweep_angle, 360);//默认为360
        barWidth = typedArray.getDimension(R.styleable.CircleBarView_bar_width, dip2px(context, 10));//默认为10dp
        typedArray.recycle();//typedArray用完之后需要回收,防止内存泄漏


        progressPaint.setColor(progressColor);
        progressPaint.setStrokeWidth(barWidth);

        bgPaint.setColor(bgColor);
        bgPaint.setStrokeWidth(barWidth);


    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        float x = 50;
        float y = 50;
        RectF rectF = new RectF(x, y, x + 300, y + 300);//建一个大小为300 * 300的正方形区域

        canvas.drawArc(mRectF,startAngle,sweepAngle,false,bgPaint);
        canvas.drawArc(mRectF,startAngle,progressSweepAngle,false, progressPaint);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int height = measureSize(defaultSize, heightMeasureSpec);
        int width = measureSize(defaultSize, widthMeasureSpec);
        int min = Math.min(width, height);// 获取View最短边的长度
        setMeasuredDimension(min, min);// 强制改View为以最短边为长度的正方形

        if (min >= barWidth * 2) {//这里简单限制了圆弧的最大宽度
            mRectF.set(barWidth / 2, barWidth / 2, min - barWidth / 2, min - barWidth / 2);
        }

    }

    private int measureSize(int defaultSize, int measureSpec) {
        int result = defaultSize;
        int specMode = View.MeasureSpec.getMode(measureSpec);
        int specSize = View.MeasureSpec.getSize(measureSpec);

        if (specMode == View.MeasureSpec.EXACTLY) {
            result = specSize;
        } else if (specMode == View.MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
        return result;
    }


    public class CircleBarAnim extends Animation {

        public CircleBarAnim() {
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            sweepAngle = interpolatedTime * 360;
            progressSweepAngle = interpolatedTime * sweepAngle * progressNum / maxNum;//这里计算进度条的比例
            postInvalidate();

            if(textView !=null&& onAnimationListener!=null){
                textView.setText(onAnimationListener.howToChangeText(interpolatedTime,progressNum,maxNum));
            }


        }
    }

    //写个方法给外部调用,用来设置动画时间
    public void setProgressNum(float progressNum, int time) {
        anim.setDuration(time);
        this.startAnimation(anim);
        this.progressNum = progressNum;
    }


    public int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public int px2dip(Context context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 设置显示文字的TextView
     * @param textView
     */
    public void setTextView(TextView textView) {
        this.textView = textView;
    }

    public interface OnAnimationListener {
        /**
         * 如何处理要显示的文字内容
         * @param interpolatedTime 从0渐变成1,到1时结束动画
         * @param progressNum 进度条数值
         * @param maxNum 进度条最大值
         * @return
         */
        String howToChangeText(float interpolatedTime, float progressNum, float maxNum);
    }



}

 

 

2.attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--注意这里的name要和自定义View的名称一致,不然在布局文件中无法引用-->
    <declare-styleable name="CircleBarView">
        <attr name="progress_color" format="color"></attr>
        <attr name="bg_color" format="color"></attr>

        <attr name="bar_width" format="dimension"></attr>

        <attr name="start_angle" format="float"></attr>
        <attr name="sweep_angle" format="float"></attr>
    </declare-styleable>
</resources>

3.布局使用

<RelativeLayout
    android:layout_width="100dp"
    android:layout_height="100dp"

    android:layout_marginTop="10dp"
    android:layout_marginRight="50dp">
    <com.qikeya.qkyxt.widgets.CircleBarView
        android:id="@+id/circle_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal"
        app:bar_width="8dp"
        app:bg_color="#FFB9DEFF"
        app:progress_color="#FFFFFFFF"
        app:start_angle="-90"
        app:sweep_angle="270" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/text_gailv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="正确率"
            android:textColor="@color/white"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/text_progres"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="23%"
            android:textColor="@color/white"
            android:textSize="25sp"
            android:textStyle="bold" />
    </LinearLayout>

</RelativeLayout>

 

4.  java代码

circle_view.setProgressNum(23,1500);
text_progress.setText("23%");

 

多谢大神https://blog.csdn.net/lly347705530/article/details/78213501的博客  让我解决了这个难题  

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值