高级UI

android 画饼图

2019-03-29  本文已影响23人  一个冬季
效果.png
1、步骤分析

问:画一个圆我们需要什么?
答:一只笔(Paint),这只笔要有颜色(Paint.setColor),需要半径(R),调用canvas.drawArc()方法来画圆

2、涉及到的知识点讲解

我们通过canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)方法来画弧,该方法接受5个参数
RectF oval:画的弧度要在这个矩形里面
startAngle:开始角度
sweepAngle:弧度划过的角度
useCenter:是否与圆心连接(与圆心连接会成扇形)
paint:画笔

onSizeChanged,该方法是是介于onLayout=>onSizeChanged=>onDraw,所以我们会通过该方法获取宽高

数学上的知识点
Math.cos(d),Math.Sin(d),这里的d是弧度,不是角度

绘制文字的方向, 象限.png

我们画的文字要分别在这4个象限里面

3、OK,大概就这样了,我们开始

初始化画笔

  TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PieView);
        textPadding = (int) typedArray.getDimension(R.styleable.PieView_textPadding, getResources().getDimensionPixelOffset(R.dimen.dp_5));//默认的边距
        textNumTextSize = (int) typedArray.getDimension(R.styleable.PieView_numTextSize, getResources().getDimensionPixelOffset(R.dimen.sp_12));//文字
        centerTextSize = (int) typedArray.getDimension(R.styleable.PieView_numTextSize, getResources().getDimensionPixelOffset(R.dimen.sp_14));//中心文字大小
        textCenterColor = typedArray.getColor(R.styleable.PieView_centerTextColor,getResources().getColor(R.color.blue_00AAFF));
        mPain = new Paint();
        mPain.setTextSize(textNumTextSize);
        mPain.setColor(Color.WHITE);
        mPain.setStyle(Paint.Style.FILL);
        mPain.setAntiAlias(true);
        rectF = new RectF();

获取圆的半径,这里-textPadding的目的是为了后面绘制文字,文字是需要在圆的外面


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        pieWidth = w;
        pieHieght = h;
        radius = Math.min(w, h) / 2 - textPadding;//textPadding文字距离
    }

开始绘制

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (pieViewBeans != null) {
            float currentAngle = 0f;
            canvas.translate(pieWidth / 2, pieHieght / 2);
            rectF.set(-radius, -radius, radius, radius);
            mPain.setTextSize(textNumTextSize);
            for (int i = 0; i < pieViewBeans.size(); i++) {
                //绘制弧形
                mPain.setColor(pieViewBeans.get(i).getColor());
                canvas.drawArc(rectF, currentAngle, pieViewBeans.get(i).getAngle(), true, mPain);
                //绘制文字
                float angle = currentAngle + pieViewBeans.get(i).getAngle() / 2;
                int textRaidus = radius;
                //正玄,余弦函数,有正负极之分
                float textX = (float) (textRaidus * Math.cos(angle * Math.PI / 180));
                float textY = (float) (textRaidus * Math.sin(angle * Math.PI / 180));
                String text = pieViewBeans.get(i).getPercenter() + "%";
                if (angle >= 0 && angle <= 90) {//第一象限
                    textY = textY + textPadding / 2;
                } else if (angle > 90 && angle <= 180) {//第二象限
                    textX = textX - textPadding;
                    textY = textY + textPadding / 2;
                } else if (angle > 180 && angle <= 270) {//第三象限
                    textX = textX - textPadding;
                    textY = textY - textPadding / 3;
                } else {//第四象限
                    textY = textY - textPadding / 3;
                }
                canvas.drawText(text, textX, textY, mPain);
                currentAngle = currentAngle + pieViewBeans.get(i).getAngle();
            }
            mPain.setColor(Color.WHITE);
            canvas.drawCircle(0, 0, radius / 2, mPain);

            //绘制中心文字
            float centerTextX = mPain.measureText(defalutStrng) / 2;
            mPain.setTextSize(centerTextSize);
            mPain.setColor(textCenterColor);
            //这里Y轴多加上 textPadding/2的原因是,我计算radius少了textPadding/2
            canvas.drawText(defalutStrng, -centerTextX, (mPain.ascent() + mPain.descent()) / 2 + textPadding/2, mPain);
        }
    }

这里需要多注意一下,正玄,余弦函数,有[-1,1]之间的区分,所以在计算文字的距离的时候,要特别注意

gitHub
https://github.com/caocao123/test/tree/master

上一篇 下一篇

猜你喜欢

热点阅读