• Android 自定义饼状图


    github 地址:https://github.com/dkest/PieView

    简单分析

      其实根据我们上面的知识已经能自己制作一个饼状图了。不过制作东西最重要的不是制作结果,而是制作思路。 相信我贴上代码大家一看就立刻明白了,非常简单的东西。不过嘛,咱们还是想了解一下制作思路:

    先分析饼状图的构成,非常明显,饼状图就是一个又一个的扇形构成的,每个扇形都有不同的颜色,对应的有名字,数据和百分比。

    经以上信息可以得出饼状图的最基本数据应包括:名字 数据值 百分比 对应的角度 颜色。

      用户关心的数据 : 名字 数据值 百分比
      需要程序计算的数据: 百分比 对应的角度
      其中颜色这一项可以用户指 

     1 public class PieData {
     2 
     3     private String name;        // 名字
     4     private float value;        // 数值
     5     private float percentage;   // 百分比
     6 
     7     private int color = 0;      // 颜色
     8     private float angle = 0;    // 角度
     9 
    10     public PieData(@NonNull String name, @NonNull float value) {
    11         this.name = name;
    12         this.value = value;
    13     }
    14 }

    自定义View:

    先按照自定义View流程梳理一遍(确定各个步骤应该做的事情):

    步骤关键字作用
    1 构造函数 初始化(初始化画笔Paint)
    2 onMeasure 测量View的大小(暂时不用关心)
    3 onSizeChanged 确定View大小(记录当前View的宽高)
    4 onLayout 确定子View布局(无子View,不关心)
    5 onDraw 实际绘制内容(绘制饼状图)
    6 提供接口 提供接口(提供设置数据的接口)

    代码如下:

     1 public class PieView extends View {
     2     // 颜色表
     3     private int[] mColors = {0xFFCCFF00, 0xFF6495ED, 0xFFE32636, 0xFF800000, 0xFF808000, 0xFFFF8C69, 0xFF808080,
     4             0xFFE6B800, 0xFF7CFC00};
     5     // 饼状图初始绘制角度
     6     private float mStartAngle = 0;
     7     // 数据
     8     private ArrayList<PieData> mData;
     9     // 宽高
    10     private int mWidth, mHeight;
    11     // 画笔
    12     private Paint mPaint = new Paint();
    13 
    14     public PieView(Context context) {
    15         this(context, null);
    16     }
    17 
    18     public PieView(Context context, AttributeSet attrs) {
    19         super(context, attrs);
    20         mPaint.setStyle(Paint.Style.FILL);
    21         mPaint.setAntiAlias(true);
    22     }
    23 
    24     @Override
    25     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    26         super.onSizeChanged(w, h, oldw, oldh);
    27         mWidth = w;
    28         mHeight = h;
    29     }
    30 
    31     @Override
    32     protected void onDraw(Canvas canvas) {
    33         super.onDraw(canvas);
    34         if (null == mData)
    35             return;
    36         float currentStartAngle = mStartAngle;                    // 当前起始角度
    37         canvas.translate(mWidth / 2, mHeight / 2);                // 将画布坐标原点移动到中心位置
    38         float r = (float) (Math.min(mWidth, mHeight) / 2 * 0.8);  // 饼状图半径
    39         RectF rect = new RectF(-r, -r, r, r);                     // 饼状图绘制区域
    40 
    41         for (int i = 0; i < mData.size(); i++) {
    42             PieData pie = mData.get(i);
    43             mPaint.setColor(pie.getColor());
    44             canvas.drawArc(rect, currentStartAngle, pie.getAngle(), true, mPaint);
    45             currentStartAngle += pie.getAngle();
    46         }
    47 
    48     }
    49 
    50     // 设置起始角度
    51     public void setStartAngle(int mStartAngle) {
    52         this.mStartAngle = mStartAngle;
    53         invalidate();   // 刷新
    54     }
    55 
    56     // 设置数据
    57     public void setData(ArrayList<PieData> mData) {
    58         this.mData = mData;
    59         initDate(mData);
    60         invalidate();   // 刷新
    61     }
    62 
    63     // 初始化数据
    64     private void initDate(ArrayList<PieData> mData) {
    65         if (null == mData || mData.size() == 0)   // 数据有问题 直接返回
    66             return;
    67 
    68         float sumValue = 0;
    69         for (int i = 0; i < mData.size(); i++) {
    70             PieData pie = mData.get(i);
    71 
    72             sumValue += pie.getValue();       //计算数值和
    73 
    74             int j = i % mColors.length;       //设置颜色
    75             pie.setColor(mColors[j]);
    76         }
    77 
    78         float sumAngle = 0;
    79         for (int i = 0; i < mData.size(); i++) {
    80             PieData pie = mData.get(i);
    81 
    82             float percentage = pie.getValue() / sumValue;   // 百分比
    83             float angle = percentage * 360;                 // 对应的角度
    84 
    85             pie.setPercentage(percentage);                  // 记录百分比
    86             pie.setAngle(angle);                            // 记录角度大小
    87             sumAngle += angle;
    88 
    89             Log.i("angle", "" + pie.getAngle());
    90         }
    91     }
    View Code

    PS: 在更改了数据需要重绘界面时要调用invalidate()这个函数重新绘制。

    效果图

  • 相关阅读:
    vsprintf函数和va_list用法详解
    copy_from_user 详解
    OK6410之蜂鸣器buzzer字符驱
    树莓派调试PCF8591遇到的小问题
    APM关键姿态控制源码讲解
    APM姿态控制流程
    没有安装gawk
    git 第一次上传本地代码到远程仓库,解决 ! [rejected] master -> master (non-fast-forward)错误
    C++ 全面刨析使用指针方法 _new _delete
    typedef&define的用法与区别
  • 原文地址:https://www.cnblogs.com/kest/p/5748823.html
Copyright © 2020-2023  润新知