随记13——我的简单自定义View之升级版的带指示的图片圆形进度条

女神镇楼
这次实在上一篇圆形进度条的基础上在进度的末尾处增加一个图片。效果如下:


解释一下:绿色背景是我们控件所占的空间大小。我想要的效果就是:在绘制的过程中,图片的中心始终跟着进度走。且进度的圆环末端中心点就是图片的中心点。理论图如下:

以上就是原理图,下面直接上代码:
/**
 * Created by Administrator on 2017/12/18.
 * 圆形进度条
 * 可增加进度图片
 */

public class CircleProgressView extends android.support.v7.widget.AppCompatTextView {

    /**
     * 圆环默认宽度
     */
    private float defaultStrokeWidth = 10;
    /**
     * 进度值0~100
     */
    private int mProgress;
    /**
     * 起始角度0~360
     * -90为正上方
     * 0为3点位置
     */
    private int fromAngle = 0;//
//    private int textSize = 14;
//    private int textColor;//默认666666;
//    private String text = "张三";
    private int mRadius;//圆弧半径 不包括圆环厚度
    private boolean isCapRound = true;//进度是开头和结尾否是圆形的
    private Paint mPaint;
    private Paint mBgPaint;
    private Paint mBitmapPaint;
    RectF ovl;//圆环内环绘制的区域
    private boolean isProgressing = false;//是否正在绘制进度 防止线程多重绘制
    Bitmap mBitmap;

    public CircleProgressView(Context context) {
        this(context, null);
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init(attrs);
    }

    private void init(AttributeSet attrs) {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.STROKE);


        mBgPaint = new Paint();
        mBgPaint.setAntiAlias(true);
        mBgPaint.setDither(true);
        mBgPaint.setStyle(Paint.Style.STROKE);

        mBitmapPaint = new Paint();
        mBitmapPaint.setAntiAlias(true);
        mBitmapPaint.setDither(true);
        mBitmapPaint.setStyle(Paint.Style.FILL);

        int strokeColor = Color.parseColor("#ff0000");
        int strokeBgColor = Color.parseColor("#f6f6f6");
        if (attrs != null){
            TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.circleProgressView);
            strokeBgColor = array.getColor(R.styleable.circleProgressView_strokeBgColor, Color.parseColor("#f6f6f6"));
            strokeColor = array.getColor(R.styleable.circleProgressView_strokeColor, Color.parseColor("#ff0000"));
            defaultStrokeWidth = (int) array.getDimension(R.styleable.circleProgressView_strokeWidth, 10);
            mRadius = (int) array.getDimension(R.styleable.circleProgressView_radius, 10);
            mProgress = array.getInteger(R.styleable.circleProgressView_progress, 0);
            fromAngle = array.getInteger(R.styleable.circleProgressView_fromAngle, 0);
            isCapRound = array.getBoolean(R.styleable.circleProgressView_isCapRound, true);
            if (fromAngle < 0){
                fromAngle = 0;
            }else if (fromAngle > 360){
                fromAngle = -90 + fromAngle%360;
            }
            array.recycle();
        }
        if (isCapRound){
            mPaint.setStrokeCap(Paint.Cap.ROUND);
        }
        mPaint.setStrokeWidth(defaultStrokeWidth);
        mPaint.setColor(strokeColor);

        mBgPaint.setStrokeWidth(defaultStrokeWidth);
        mBgPaint.setColor(strokeBgColor);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_marke);


        if (mBitmap != null){
            if (mBitmap.getWidth() > defaultStrokeWidth && mBitmap.getHeight() > defaultStrokeWidth){
                setPadding((int)(mBitmap.getWidth() - defaultStrokeWidth)/2, (int)(mBitmap.getHeight() - defaultStrokeWidth)/2, (int)(mBitmap.getWidth() - defaultStrokeWidth)/2, (int)(mBitmap.getHeight() - defaultStrokeWidth)/2);
            }else if (mBitmap.getWidth() > defaultStrokeWidth && mBitmap.getHeight() <= defaultStrokeWidth){
                setPadding((int)(mBitmap.getWidth() - defaultStrokeWidth)/2, 0, (int)(mBitmap.getWidth() - defaultStrokeWidth)/2, 0);
            }else if (mBitmap.getWidth() <= defaultStrokeWidth && mBitmap.getHeight() > defaultStrokeWidth){
                setPadding(0, (int)(mBitmap.getHeight() - defaultStrokeWidth)/2, 0, (int)(mBitmap.getHeight() - defaultStrokeWidth)/2);
            }
//            ovl = new RectF(getPaddingLeft() + 0 + defaultStrokeWidth/2, getPaddingTop() + 0  + defaultStrokeWidth/2, 2 * mRadius -  + defaultStrokeWidth/2 - getPaddingRight(), 2 * mRadius -  + defaultStrokeWidth/2 - getPaddingBottom());
        }else{
//            ovl = new RectF(0 + defaultStrokeWidth/2, 0  + defaultStrokeWidth/2, 2 * mRadius -  + defaultStrokeWidth/2, 2 * mRadius -  + defaultStrokeWidth/2);
        }
        ovl = new RectF(getPaddingLeft() + defaultStrokeWidth/2, getPaddingTop()  + defaultStrokeWidth/2, getPaddingLeft() + 2 * mRadius  + defaultStrokeWidth * 3/2, getPaddingTop() + 2 * mRadius + defaultStrokeWidth*3/2);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        int width = MeasureSpec.getSize(widthMeasureSpec);
//        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
//        int height = MeasureSpec.getSize(heightMeasureSpec);
//        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        setMeasuredDimension((int)(getPaddingLeft() + getPaddingRight() + 2 *(mRadius + defaultStrokeWidth)),  (int)(getPaddingTop() + getPaddingBottom() + 2 *(mRadius + defaultStrokeWidth)));
//        setMeasuredDimension(getDefaultSize(width, widthMeasureSpec), getDefaultSize(height, heightMeasureSpec));


    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        ovl = new RectF(0 + defaultStrokeWidth/2, 0  + defaultStrokeWidth/2, getMeasuredWidth() -  + defaultStrokeWidth/2, getMeasuredHeight() -  + defaultStrokeWidth/2);
        canvas.drawArc(ovl, fromAngle - 90, 360, false, mBgPaint);
        canvas.drawArc(ovl, fromAngle - 90, 360 * mProgress/100, false, mPaint);
//        canvas.drawText(text, getWidth()/2, getHeight()/

        canvas.drawBitmap(mBitmap, (float) (mRadius + defaultStrokeWidth/2 + (mRadius + defaultStrokeWidth/2) *Math.sin( 2*PI/360*360 * mProgress/100) - mBitmap.getWidth()/2 + getPaddingLeft() + defaultStrokeWidth/2),
                (float)(mRadius + defaultStrokeWidth/2 - (mRadius + defaultStrokeWidth/2) *Math.cos( 2*PI/360*360 * mProgress/100) - mBitmap.getHeight()/2 + getPaddingTop() + defaultStrokeWidth/2), mBitmapPaint);
    }


    public void setProgress(int progress){
        if (progress <= 0){
            progress = 0;
            mProgress  = 0;
            postInvalidate();
        }else if (progress > 100){
            progress = 100;
        }

        //解决多个线程同时修改界面的问题
        if (isProgressing)
            isProgressing = false;
        final int finalProgress = progress;
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                isProgressing = true;
                new Thread() {
                    @Override
                    public void run() {
                        super.run();
                        //防止上一个线程的影响
                        for (int i = 0; i < finalProgress; i++) {
                            mProgress = i;
                            postInvalidate();
                            try {
                                Thread.sleep(30);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            if (!isProgressing) {
                                break;
                            }
                        }
                        isProgressing = false;
                    }
                }.start();
            }
        }, 50);

    }

}
用法跟圆形进度条一样,不清楚可以看上一篇。多了两条属性
<attr name="resId" format="integer"/>
<attr name="radius" format="dimension"/>

That is all。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值