微信公众号:伴职创作
IT类、哲学、散文、叙事情感类、小说…欢迎你来投稿。

在读这篇文章之前,推荐先读:引文
1.1. PieChart简单实现
1.2. 封装PieChart实现扇形图
1.3. 封装PieChart实现圆环图
PieChart是MPAndroidChart组件中用来实现饼状图的自定义ViewGroup,通过PieChart一些属性设置就能实现扇形图或圆环图。
首先看看PieChart简单实现的效果图,如图1-1:

由图1-1可以看出,PieChart饼状图实际是可以分Chart图(包括圆环图和内部白色圆形图),Legend图例,以及Description图表描述三个部分组成。
通过PieChart来实现这样的饼状图,只需要二步:
一、在布局文件中引入PieChart
<com.github.mikephil.charting.charts.PieChart
    android:id="@+id/pieChart"
    android:layout_width="match_parent"
    android:layout_height="200dp"/>注意:PieChart在布局文件中一定要设置layout_height的明确值,如果设置成match_parent或wrap_content,PieChart会因无法确定图表的大小,而显示不完全(或Chart图无法显示)。
二、将PieChart设置数据
首先通过PieChart的布局ID在相应窗体中找到PieChart对象。
PieChart pieChart = findViewById(R.id.z_pie_chart);其次设置PieChart相关数据。
PieChart提供了PieChart.setData(PieData data)来设置数据,PieData通过new PieData(PieDataSet dataSet)来进行实例化,而PieDataSet类包含List
private void initPieChartData() {
    // 设置假数据
    List<PieEntry> yVals = new ArrayList<>();
    List<Integer> colors = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
        if (i == 0) {
            PieEntry pieEntry = new PieEntry(0.3f, "运费冻结");
            yVals.add(pieEntry);
            colors.add(Color.parseColor("#1B9E0D"));
        } else if (i == 1) {
            PieEntry pieEntry = new PieEntry(0.1f, "待扣税金");
            yVals.add(pieEntry);
            colors.add(Color.parseColor("#67E020"));
        } else {
            PieEntry pieEntry = new PieEntry(0.6f, "可提现余额");
            yVals.add(pieEntry);
            colors.add(Color.parseColor("#E02020"));
        }
    }
    // 构造PieDataSet
    PieDataSet pieDataSet = new PieDataSet(yVals, null);
    // 设置图表颜色
    // yVals与colors数据数量相等,颜色与值要一一对应
    pieDataSet.setColors(colors);
    // 构造pieData
    PieData pieData = new PieData(pieDataSet);
    // 显示数据
    pieChart.setData(pieData);
}其中PieDataSet.setColors(List
通过上面两步就能实现图1-1中的饼状图。
封装PieChart实现扇形图的目的是通过自定义PieChart来简化PieChart所提供的操作方法。
本文是定义一个ZPieChart类来继承PieChart,从而实现对PieChart方法的封装。
首先看看最终简化的初始效果图,图1-2:

具体思路:
1. 自定义ZPieChart继承PieChart。
在ZPieChart中实现三个构造方法:
/**
 * 扇形图
 *
 * @author 邹峰立
 */
public class ZPieChart extends PieChart {
    public ZPieChart(Context context) {
        this(context, null);
    }
    public ZPieChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public ZPieChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initPieChart();
    }
    // 初始化
    private void initPieChart() {
    }
}2. 绘制真正的扇形图。
图1-1显然不是真正的扇形图,更多是一个圆环,那么如何修正该伪扇形呢?
分析:Chart图内部白色圆形图实际上是由一层大的白色半透明圆形图覆盖在一层小的白色圆形图上形成。
方案一:通过PieChart提供的设置两层白色圆形图半径的方法,将其半径设为0,从而实现隐藏的效果。
具体代码,代码1:
// 中间实心圆半径
PieChart.setHoleRadius(0f);
// 中间半透明圆半径
PieChart.setTransparentCircleRadius(0f);方案二:PieChart提供直接控制Chart图中间白色圆形图的隐藏和显示方法。
具体代码,代码2:
// 隐藏中心圆
PieChart.setDrawHoleEnabled(false);‘代码1’或‘代码2’都可以放在初始化initPieChart方法中进行实现。
3. 隐藏扇形Chart图上面的文字。
扇形Chart图上面的文字包含两部分,第一部分是扇形所占的比例,第二部分是扇形的内容描述。
隐藏扇形的内容描述通过PieChart提供的方法即可。
// 隐藏扇形的内容描述
PieChart.setDrawSliceText(false);该方法会提示已过时,可以使用以下方法代替。
PieChart.setDrawEntryLabels(false);关于扇形所占的比例,就需要通过PieDataSet来进行设置。
// 是否在图上显示数值
PieDataSet.setDrawValues(false);4. 处理Legend图例,垂直排列并且居于Chart图右方,并且色块设置为圆角。
对图例的处理就需要通过Legend来处理了,首先可以获取PieChart的Legend的实例。
Legend mLegend = PieChart.getLegend();其次设置图例垂直居中右显示。
// 设置图例垂直排列
mLegend.setOrientation(Legend.LegendOrientation.VERTICAL);
// 图例居中显示
mLegend.setVerticalAlignment(Legend.LegendVerticalAlignment.CENTER);
// 图例右对其
mLegend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);最后设置色块为圆角。
// 设置图例色块为圆角
mLegend.setForm(Legend.LegendForm.CIRCLE);Legend的其他细节处理。
// y轴的间距
mLegend.setYEntrySpace(5f);
// 图例文字的颜色
mLegend.setTextColor(Color.parseColor("#000000"));
// 图例文字的大小
mLegend.setTextSize(14);5. 隐藏Description图表描述区。
对图表描述区的操作就需要通过Description来进行操作。同样先获取Description对象,然后进行隐藏操作。
Description mDescription = getDescription();
// 取消右下角描述
mDescription.setEnabled(false);6. 完善扇形图大小,即设置扇形图上下左右距离。
// 图相对于上下左右的偏移
PieChart.setExtraOffsets(18, 18, 18, 18);PieChart的其他细节处理。
// 初始旋转角度
PieChart.setRotationAngle(0);
// 不可以手动旋转
PieChart.setRotationEnabled(false);7. 封装数据类型。
首先定义数据对象,在该对象中含有显示扇形图表相关数据,例如比例、扇形颜色等,还要能设置图例色块标签等。
* 扇形图数据
 *
 * @author 邹峰立
 */
public class PieChartBean<T> {
    private int color;// 扇形颜色 16进制
    private String colorStr;// 扇形颜色 字符串
    private float proportion;// 比例
    private String label;// 图例对应色块标签
    private T data;// 真实数据
}最后针对封装的数据类型实现图表设值。
/**
 * 设置数据
 *
 * @param list        待显示数据
 * @param legendLabel 图例标签
 */
public ZPieChart setPieData(ArrayList<PieChartBean> list, String legendLabel) {
    if (list != null && list.size() > 0) {
        List<PieEntry> yVals = new ArrayList<>();
        List<Integer> colors = new ArrayList<>();
        for (PieChartBean data : list) {
            PieEntry pieEntry = new PieEntry(data.getProportion(), data.getLabel(), data.getData());
            yVals.add(pieEntry);
            // 添加颜色
            colors.add(data.getColor());
        }
        if (yVals.size() > 0) {
            pieDataSet = new PieDataSet(yVals, legendLabel);
            pieDataSet.setColors(colors);
        }
        // 是否在图上显示数值
        pieDataSet.setDrawValues(false);
        // 待显示数据
        pieData = new PieData(pieDataSet);
        this.setData(pieData);
    }
    return this;
}
/**
 * 设置数据
 *
 * @param list 待显示数据
 */
public ZPieChart setPieData(ArrayList<PieChartBean> list) {
    return setPieData(list, null);
}至此如图1-2的效果图就实现了。那么该如何使用ZPieChart呢?
8. ZPieChart具体使用。
同样,现在布局文件中引入:
<cc.ibooker.zmpandroidchartlib.ZPieChart
    android:id="@+id/z_pie_chart"
    android:layout_width="match_parent"
    android:layout_height="300dp" />其次在ZPieChart所在窗体设置数据:
// 初始化控件
private void initView() {
    // 扇形图
    pieChart = findViewById(R.id.z_pie_chart);
    initPieChart();
}
// 显示扇形图
private void initPieChart() {
    // 初始化数据数据
    ArrayList<PieChartBean> list = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
        PieChartBean<String> pieChartBean = new PieChartBean<>();
        list.add(pieChartBean);
        if (i == 0) {
            pieChartBean.setColorStr("#1B9E0D");
            pieChartBean.setProportion(0.3f);
            pieChartBean.setLabel("运费冻结");
        } else if (i == 1) {
            pieChartBean.setColorStr("#67E020");
            pieChartBean.setProportion(0.1f);
            pieChartBean.setLabel("待扣税金");
        } else {
            pieChartBean.setColorStr("#E02020");
            pieChartBean.setProportion(0.6f);
            pieChartBean.setLabel("可提现余额");
        }
    }
    // 显示数据
    pieChart.setPieData(list);
}了解了扇形图的设计,对于圆环图的实现就没有那么难了。基本思路跟封装PieChart实现扇形图类似。
首先看看封装的环形图实现的初始化效果, 如图1-3:

具体思路:
1. 自定义ZRingChart继承PieChart。
/**
 * 圆环图
 *
 * @author 邹峰立
 */
public class ZRingChart extends PieChart {
    public ZRingChart(Context context) {
        this(context, null);
    }
    public ZRingChart(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public ZRingChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initPieChart();
    }
    // 初始化
    private void initPieChart() {
    }
}2. 完善圆环图大小。
上面已经说明过Chart图内部圆环是由一个大的半透明圆形图和一个白色的圆形图叠加形成,在这里需要把半透明圆形图隐藏,然后调整白色圆形图半径大小。隐藏半透明圆形图可以通过设置其半径为0,来实现隐藏效果。
// 隐藏半透明圈
PieChart.setTransparentCircleRadius(0f);
// 设置中间圆半径
PieChart.setHoleRadius(62f);3. 处理Chart图上面的文字。
Chart图上的文字处理需要通过PieDataSet类来设置,而本例中需要设置图表上文字显示和设置其大小。
// 是否在图上显示数值
PieChart.setPieDataSetDrawValues(true);
// 设置图表文字的大小
PieDataSet.setValueTextSize(15);其中4、5、6、7可以直接使用扇形图的实现。
8. ZRingChart具体使用。
首先将ZRingChart引入布局文件。
<cc.ibooker.zmpandroidchartlib.ZRingChart
    android:id="@+id/z_pie_chart"
    android:layout_width="match_parent"
    android:layout_height="300dp" />其次在ZRingChart所在窗体设置数据:
// 初始化控件
private void initView() {
    // 扇形图
    pieChart = findViewById(R.id.z_pie_chart);
    initPieChart();
}
// 显示扇形图
private void initPieChart() {
    // 初始化数据数据
    ArrayList<PieChartBean> list = new ArrayList<>();
    for (int i = 0; i < 3; i++) {
        PieChartBean<String> pieChartBean = new PieChartBean<>();
        list.add(pieChartBean);
        if (i == 0) {
            pieChartBean.setColorStr("#1B9E0D");
            pieChartBean.setProportion(0.3f);
            pieChartBean.setLabel("运费冻结");
        } else if (i == 1) {
            pieChartBean.setColorStr("#67E020");
            pieChartBean.setProportion(0.1f);
            pieChartBean.setLabel("待扣税金");
        } else {
            pieChartBean.setColorStr("#E02020");
            pieChartBean.setProportion(0.6f);
            pieChartBean.setLabel("可提现余额");
        }
    }
    // 设置中间文字
    pieChart.setCenterText(generateCenterText(8888.88f));
    pieChart.setCenterTextColor(Color.parseColor("#999999"));
    pieChart.setCenterTextSize(12);
    // 显示数据
    pieChart.setPieData(list);
}
/**
  * 中间文字绘制
  *
  * @param sum 总数
  */
private SpannableString generateCenterText(float sum) {
    String total = Float.toString(sum);
    SpannableString s = new SpannableString("总收入\n" + total + "\n(万元)");
    int start = 4;
    int end = 4 + total.length();
    s.setSpan(new RelativeSizeSpan(2f), start, end, 0);
    s.setSpan(new ForegroundColorSpan(Color.parseColor("#000000")), start, end, 0);
    return s;
}关于基于MPAndroidChart开发PieChart扇形图、圆环图,至此就完成了。
