安卓中如何快速的绘制饼状图

983

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战

安卓中如何快速的绘制饼状图

在很多的场景中,大家都要用到图表类型,虽然很多人都有使用自定义视图的能力,但在一般的工作中,大家一般还是用轮子的比较多。原因也很简单,自己使用原生代码去写,需要熟练运用自定义视图的知识,其次需要花费大量的时间,最后还要解决解决bug。著名的图表库已经可以很大程度的满足需求了,即使有些定制化的需求,通过修改这些轮子也能达到效果。

一、选择图表库

筛选最著名的两个图表库

  1. HelloCharts

  2. MPAndroidChart

截止到目前,他们的Star分别是 7.3K、34.5K.

当然是选择星星比较多的啦。

因为星星多的库,一般生态也会比较大,遇到疑难杂症就比较容易搜索出来。

二、效果图

效果图.png

三、抛出几个问题

  1. 当数据值为0时怎么在饼状图上显示?

  2. 当饼状图中数据很多时,数据重叠怎么办?

四、开始编码

4.1 引入图标库


// 引入图表

implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'

并且,在安卓开发工具北极狐上,需要在项目根目录的settings.gradle添加代码


repositories {

maven { url "https://jitpack.io" }

}

4.2 XML中引入视图


<com.github.mikephil.charting.charts.PieChart

android:id="@+id/pie_chart"

android:layout_width="match_parent"

android:layout_height="match_parent" />

4.3 构建数据

一般来说,我们需要的数据结构是 标签+数据,比如:张三+分数,所以我们构建出这个对象。


class ChartBean {

private String label;

private int value;

}

我们构建多一点,为了模拟0分的现象,我们也构建两个零分的数据。


private List<ChartBean> getData() {

List<ChartBean> list = new ArrayList<>();

list.add(new ChartBean("张三", 1));

list.add(new ChartBean("李四", 2));

list.add(new ChartBean("王五", 3));

list.add(new ChartBean("赵六", 4));

list.add(new ChartBean("孙七", 0));

list.add(new ChartBean("周八", 0));

return list;

}

4.4 添加配置

有一些很常用的配置,比如说

去除右下角的描述 -> getDescription().setEnabled(false)

实心圆 或 空心圆 -> setDrawHoleEnabled(false);

不使用百分比 -> setUsePercentValues(false);

为了方便大家拷贝,我把initPieChart贴出来。


private void initPieChart(PieChart pieChartView, @NonNull List<ChartBean> chartResultBeans) {

pieChartView.setVisibility(View.VISIBLE);

pieChartView.setRotationAngle(45);

// 去除 右下角的描述

pieChartView.getDescription().setEnabled(false);

// 实心圆 或 空心圆

pieChartView.setDrawHoleEnabled(false);

// 不使用百分比,不然会被计算

pieChartView.setUsePercentValues(false);

// 隐藏label,设置 label 文字大小

pieChartView.setDrawEntryLabels(false);

pieChartView.setEntryLabelTextSize(24);

// 设置legend 文字大小

pieChartView.getLegend().setTextSize(20);

pieChartView.getLegend().setTextColor(Color.WHITE);

// 构建数据

List<PieEntry> strings = new ArrayList<>();

for (ChartBean bean : chartResultBeans) {

if (bean != null) {

if (bean.getValue() == 0)

strings.add(new PieEntry(0.3f, bean.getLabel(), bean));

else

strings.add(new PieEntry(bean.getValue(), bean.getLabel(), bean));

}

}

// 右下角的label 不需要

PieDataSet dataSet = new PieDataSet(strings, "");

// 添加颜色(添加多种,避免造成颜色一样的情况)

ArrayList<Integer> colors = new ArrayList<>();

colors.add(getResources().getColor(R.color.chart_1));

colors.add(getResources().getColor(R.color.chart_2));

dataSet.setColors(colors);

// format value

dataSet.setValueFormatter(new PieCenterFormatter("分"));

// 指示信息在饼状图外

dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);

dataSet.setValueLineColor(Color.BLACK);

PieData pieData = new PieData(dataSet);

pieData.setDrawValues(true); // 需要Value

pieData.setValueTextSize(24); // 字体大小

pieData.setValueTextColor(Color.WHITE);

pieChartView.setData(pieData);

}

4.5 ValueFormatter

formatter的含义是将显示的内容格式化。

我格式化的格式是: 标签+值+单位


public static class PieCenterFormatter extends ValueFormatter {

private final String mUnit;

public PieCenterFormatter(String unit) {

this.mUnit = unit;

}

@Override

public String getPieLabel(float value, PieEntry pieEntry) {

ChartBean bean = (ChartBean) pieEntry.getData();

if (bean != null) {

String unit = TextUtils.isEmpty(mUnit) ? "" : mUnit;

return bean.getLabel() + ":" + bean.getValue() + unit;

}

return "";

}

}

这样一个简单的饼状图就完成了。

4.6 解决问题

  1. 当数据值为0时怎么在饼状图上显示?

当数据为0时,在饼状图上我们应该显示小部分区域,还是不显示,这首先是咨询产品经理。 什么? 没有产品经理,那就按常规的,给他显示小部分区域,在代码上我们这么实现。


if (bean.getValue() == 0)

strings.add(new PieEntry(0.3f, bean.getLabel(), bean));

  1. 数据太多时重叠的问题。

这个问题比较复杂,还在该库的生态庞大,有人帮我们解决了这部分问题。

我们自定义一个 MyPieChart,然后使用它。

MyPieChart怎么写,参考:数据重叠解决办法