自定义View之圆环的绘制

前言

这个也算是已经写过的例子了,整理了一下就拿出来了,参考了一篇文章,并在原有的基础上优化了圆环上下段之间的衔接间隔问题,时间久远,找不到文章的地址了,如果有帮忙找到,请联系我加上去,谢谢.

效果

name

代码

public class CircleRingView extends View {
    private static final String TAG = "SleepRingView";
    private int[] mColors;
    private Paint circlePaint;                                                                      //表盘外轮廓画笔
    private Paint linePaint;                                                                       // 表盘内短线画笔
    private int mWidth;
    private int mHeight;
    private float startPercent = 0;
    private float initStartPercent;
    //圆环的画笔
    private Paint cyclePaint;
    //圆的直径
    private float mRadius = 300;
    //圆的粗细
    private float mStrokeWidth = 80;
    private List<CircleRingMode> ringModes = new ArrayList<>();
    private Context mContext;
    private int startY = 0;
    private ArgbEvaluator argbEvaluator = new ArgbEvaluator();//颜色渐变插值器
    private int radius;

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

    public CircleRingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        mColors = new int[]{
                context.getResources().getColor(R.color.colorSleepGradient2),
                context.getResources().getColor(R.color.colorSleepGradient3),
                context.getResources().getColor(R.color.colorSleepGradient),
                context.getResources().getColor(R.color.colorSleepGradient4)
        };
        initPaint();
    }

    /**
     * 创建所有的paint
     */
    private void initPaint() {
        int strokeWidth = UnitUtil.dp2px(mContext, 2.5f);
        circlePaint = getAvailablePaint(Color.BLUE, strokeWidth, Paint.Style.STROKE);
        linePaint = getAvailablePaint(mContext.getResources().getColor(R.color.colorSleepGradient), strokeWidth, Paint.Style.FILL);
        linePaint.setTextSize(UnitUtil.dp2px(getContext(), 12));
        mStrokeWidth = UnitUtil.dp2px(mContext, 24);
        cyclePaint = getAvailablePaint(Color.BLUE, (int) mStrokeWidth, Paint.Style.STROKE);
        startY = UnitUtil.dp2px(mContext, 10);
    }

    private Paint getAvailablePaint(int color, int strokeWidth, Paint.Style style) {
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FAKE_BOLD_TEXT_FLAG);
        paint.setAntiAlias(true);
        paint.setColor(color);
        paint.setStyle(style);
        paint.setStrokeWidth(strokeWidth);

        paint.setDither(true);//设置图像抖动处理
        paint.setStrokeJoin(Paint.Join.ROUND);//画笔线等连接处的轮廓样式
        paint.setSubpixelText(true);
        return paint;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        circlePaint.setShader(new LinearGradient(3, 3, mWidth - 3, mHeight - 3, mColors, null, Shader.TileMode.CLAMP));
        canvas.drawCircle(mWidth / 2, mHeight / 2, radius, circlePaint);
        mRadius = radius * 2 - startY * 6;
        canvas.translate(mWidth / 2 - mRadius / 2, mHeight / 2 - mRadius / 2);
        if (ringModes.size() == 0)
            return;
        //画圆环
        drawCycle(canvas);
        drawSquare(canvas);
    }

    //画圆环
    private void drawCycle(Canvas canvas) {
        float sweepPercent = 0f;
        CircleRingMode mode;
        startPercent = initStartPercent;
        for (int i = 0; i < ringModes.size(); i++) {
            mode = ringModes.get(i);
            cyclePaint.setColor(mode.getColorValue());
            startPercent += (sweepPercent - 0.5f);
            if (i < 2) {
                sweepPercent = (mode.getProgress() + 0.5f) * 360 / 100f;
                startPercent -= 1f;
            } else if (i == ringModes.size() - 1) {
                sweepPercent = 360f + initStartPercent - startPercent - 0.5f;
            } else {
                sweepPercent = mode.getProgress() * 360 / 100f;
            }
            canvas.drawArc(new RectF(0, 0, mRadius, mRadius), startPercent, sweepPercent, false, cyclePaint);
        }
    }

    private void drawSquare(Canvas canvas) {
        int base = Math.min(mWidth, mHeight) / 25;
        int startTop = mHeight / 2 - base * 3;
        int startLeft = mWidth / 2 + base;
        for (CircleRingMode mode : ringModes) {
            linePaint.setColor(mode.getColorValue());
            canvas.drawRect(new Rect(startLeft, startTop, startLeft + base, startTop + base), linePaint);
            canvas.drawText(mode.getProgress() + "%", startLeft + base + 10, startTop + base, linePaint);
            startTop += base * 2;
        }
    }

    /**
     * 获取宽和高
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        mHeight = getDefaultSize(getSuggestedMinimumWidth(), heightMeasureSpec);
        radius = Math.min(mWidth / 2, mHeight / 2) - UnitUtil.dp2px(mContext, 24);
        Log.d(TAG, "onMeasure: mWidth: " + mWidth + ",mHeight: " + mHeight);
    }


    public void setData(List<CircleRingMode> modeList) {
       this.setData(modeList,0);
    }

    public void setData(List<CircleRingMode> modeList, float hour) {
        if (modeList.size() == 0)
            return;
        if (this.ringModes.size() > 0)
            this.ringModes.clear();
        this.ringModes.addAll(modeList);
        this.startPercent = this.initStartPercent = 360 * hour / 24f - 90;
        invalidate();
    }
}

最后

Github项目地址

有不对的地方欢迎留言指正,不胜感激.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值