android饼状统计图

86 阅读2分钟

我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!

  • 引言

      开发会遇到需要的图表,用一个三方库太大比如MPandroidchart,这时候就可以自己来自定义个图表控件,近日我就开发了个饼状图,用来显示各板块占比和信息显示,并加入了动画,某块模块放大,自定义设置板块颜色、字体颜色等功能,可直接拿来使用。

  • 设计思路

      非动画实现思路,先绘制一个个弧形版块拼接成圆,同一圆心,再绘制一个小点的带透明度的白色圆盖在其上,然后绘制中心的孔,即纯白的圆盖在最上面,最后根据计算,将文字绘制在版块的角平分线上,居在透明圆边和外圆边的中心。
      
      
    
  • 代码

onDraw方法中

public void draw(Canvas canvas) {
        super.draw(canvas);
        //将画布绘成白色
        canvas.drawColor(Color.WHITE);
        //平移画布,使(0,0)点至中心,便于计算
        canvas.translate(getWidth()/2,getHeight()/2);
        calculate();
        
        if (showAnimator){
            drawByAnim(canvas);    //动画绘制
        }else {
            drawByNormal(canvas);    //普通绘制
        }
    }

这边就是给画笔设置对应颜色,若未设置则随机取色,这边还有个功能就是使该板块有凸起的效果,其实就是采取画布平移(canvas.translate),根据该板块角平分线往外拉一定距离;绘制弧形,使用方法canvas.drawArc(RectF,起始绘制角度,旋转绘制角度,是否包含圆心,画笔);最后将画布恢复到之前保存的状态即为外角平分线平移的状态;将该板块的角度累加到当前角度中去,这样绘制下一板块的起始角度就在这个版块之后了。


/**
     * 非动画绘制
     */
    private void drawByNormal(Canvas canvas){
        //循环绘制各模块
        for (int i=0;i<count;i++){
            if (0 == getData().get(i).getColor()){
                int color = getRandColor();
                mOutPaint.setColor(color);
                getData().get(i).setColor(color);
            }else {
                mOutPaint.setColor(getData().get(i).getColor());
            }
            //计算该板块角度
            float sweepAngle = getData().get(i).getData()/sumData*360f;
            //保存当前画布状态
            canvas.save();
            //当前模块角平分线的sin和cos值
            if (getData().get(i).isRaised()){
                float mathCos = (float) (Math.cos((sweepAngle/2+mCurrentDegree)/180f*Math.PI));
                float mathSin = (float) (Math.sin((sweepAngle/2+mCurrentDegree)/180f*Math.PI));
                //若该板块设置凸起,平移画布,使其与周边各块产生间距,并突出
                canvas.translate(mathCos*mSpace, mathSin*mSpace);
            }
            //绘制外圆
            canvas.drawArc(mRadiusRectF,mCurrentDegree,sweepAngle,true,mOutPaint);
            //恢复平移前的状态
            canvas.restore();
 
            mCurrentDegree += sweepAngle;
        }
        //绘制透明圆和中心圆孔
        mAlphaPaint.setAlpha((int) (mAlpha*255));
        canvas.drawCircle(0,0,mRadius*mAlphaRadiusPercent,mAlphaPaint);
        canvas.drawCircle(0,0,mRadius*mHoleRadiusPercent,mHolePaint);
        //绘制版块文字
        drawTextInner(canvas);
 
        if (showCenterText) {
            //绘制中心文字
            Paint.FontMetrics metrics = mCenterTextPaint.getFontMetrics();
            float textHeight = Math.abs(metrics.descent - metrics.ascent);
            canvas.drawText(mCenterText, 0, textHeight / 2 - metrics.descent, mCenterTextPaint);
        }
    }
  • 效果

image.png