MPAndroidChart 是 Android 平台上一个强大的 Chart 开源库,支持众多图形:
- 折线图(Line Chart)
- 柱状图(Bar Chart)
- 饼图(Pie Chart)
- 散点图(Scatter Chart )
- 蜡烛图/K线图(Candle Stick Chart)
- 气泡图(Bubble Chart)
- 雷达图(Radar Chart)
同时也提供了 iOS 版本的实现库 Charts,实现效果甚至 API 与 MPAndroidChart 基本一致。
功能如此强大,使用起来却不简单。庞大的 API 会让你无处下手,有时为了实现某一效果,不得不反复调试以得到正确的 API 调用。
下面我将以一个简单的柱状图为例,记录一下详细的操作过程。
先看一下最终实现的效果:
img 1
在开始 Coding 之前,我们先来简单分析一下这张图。
- x 轴上的省份名称有角度倾斜;
- y轴上的数字千分位展示;
- 点击柱子时弹出图层;
- 单屏显示 5 个柱子;
- 表格区域的灰色背景;
- 可左右拖拽。
来吧,我们一步一步来解决。
一、一个最简单的 Bar Chart
- 创建 xml 布局
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="200dp" />
- 设置数据
BarChart chart = findViewById(R.id.chart);
List<BarEntry> values = new ArrayList<>();
for (int i = 0; i < 10; i++) {
float yVal = (float) (Math.random() * 10);
values.add(new BarEntry(i, yVal));
}
BarDataSet dataSet = new BarDataSet(values, "");
BarData data = new BarData(dataSet);
// 设置数据
chart.setData(data);
OK,运行一下,看看效果。
img 2
呃...这和我们的效果图相差甚远呐!看来我们的任务还是很艰巨的。
二、开启美化之路
- 去除图表描述,即右下角的“Description Label”字样
chart.getDescription().setEnabled(false);
- 去除左下角的小方块。好吧,其实它叫
图例
chart.getLegend().setEnabled(false);
- x 轴
XAxis xAxis = chart.getXAxis();
// x 轴显示在下方
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
// x 轴文字大小
xAxis.setTextSize(12f);
// x 轴文字颜色
xAxis.setTextColor(Color.parseColor("#555555"));
// x 轴文字旋转
xAxis.setLabelRotationAngle(-25);
// 移除 x 轴线
xAxis.setDrawAxisLine(false);
// 移除表格中的竖线
xAxis.setDrawGridLines(false);
- y 轴
注意到没有,默认是有左右两个 y 轴的。我们只保留右侧的就可以。
// 移除左侧 y 轴
chart.getAxisLeft().setEnabled(false);
YAxis yAxis = chart.getAxisRight();
// y 轴文字大小
yAxis.setTextSize(12);
// y 轴文字颜色
yAxis.setTextColor(Color.parseColor("#999999"));
// 移除 y 轴线
yAxis.setDrawAxisLine(false);
// 表格中横线的颜色
yAxis.setGridColor(Color.parseColor("#DDDDDD"));
// 表格中横线的宽度
yAxis.setGridLineWidth(0.5f);
- 柱子
BarDataSet dataSet = new BarDataSet(values, "");
// 柱子的颜色
dataSet.setColor(Color.parseColor("#4267B1"));
// 柱子的高亮颜色
dataSet.setHighLightColor(Color.parseColor("#043B8F"));
BarData data = new BarData(dataSet);
// 去除柱子上方的数值
data.setDrawValues(false);
// // 柱子的宽度(相对宽度)
data.setBarWidth(0.2f);
// x 轴显示的数值数量
xAxis.setLabelCount(Math.min(values.size(), 5));
- 手势
// 可以拖拽
chart.setDragEnabled(true);
// 禁止水平缩放
chart.setPinchZoom(false);
// 禁止竖直缩放
chart.setScaleEnabled(false);
- 表格背景色
chart.setDrawGridBackground(true);
chart.setGridBackgroundColor(Color.parseColor("#FAFAFA"));
- 柱子的数量
chart.setData(data);
// 柱子的数量
chart.setVisibleXRange(5, 5);
注意,该方法必须在setData
之后执行。
好了,先让我们看一下效果:
img 3
嗯,有点样子了。不过目前图表上的数值都是测试数据,让我们来填充真实数据吧。
三、填充你的数据
- 创建数据类
public class Company {
private String province;
private int count;
public Company(String province, int count) {
this.province = province;
this.count = count;
}
// Getter
}
- 生成一些数据,这些数据最终会体现在图表上
private List<Company> generateData() {
List<Company> companies = new ArrayList<>();
companies.add(new Company("江苏", 1302));
companies.add(new Company("山东", 3450));
// ...
return companies;
}
- 设置数据
List<Company> companies = generateData();
List<BarEntry> values = new ArrayList<>();
for (int i = 0; i < companies.size(); i++) {
Company company = companies.get(i);
values.add(new BarEntry(i, company.getCount()));
}
OK,看看效果:
很好,柱子和 y 轴已经正确显示了我们的数据。
不过 x 轴怎么还是数值呢,应该显示省份才对啊。其实看一下上面设置数据的地方,
BarEntry
接受两个参数,第一个是x轴数值,第二个是y轴数值。此处x 轴设置了一个整型 index
值,所以就把这个值显示出来了。那么我把省份名称放在第一个参数里不就可以了吗,答案是NO。BarEntry
只接受 float 类型的数值。那么我们该怎么解决呢?但是是数值格式化。
四、数值格式化 x 轴
要进行数值格式化,只需要调用 setValueFormatter
就可以。
xAxis.setValueFormatter(new IndexAxisValueFormatter(xValues));
MPAndroidChart 内置了很多数值格式化器(ValueFormatter),如 PercentFormatter
、LargeValueFormatter
以及上面的 IndexAxisValueFormatter
等。如果内置的满足不了需求,你也可以自定义自己的格式化器。
其实仔细观察一下, 右侧 y 轴的数值是有千分位的,但是我们并没有对它进行设置,是因为它使用了默认的数值格式化器。
img 5嗯,这次可以了。
五、最后一步,设置 Marker View
什么是 Marker View? 当点击柱子时,弹出来的图层就是 Marker View,一般用来展示数据的详细信息。
要显示 Marker View 也非常简单:
// 启用 Marker View
chart.setDrawMarkers(true);
// 设置 Marker View
chart.setMarker(new CompanyMarker(this, companies));
其中 CompanyMarker
是我们自定义的 Marker :
class CompanyMarker extends MarkerView {
private TextView contentView;
private List<Company> companies;
public CompanyMarker(Context context, List<Company> companies) {
// 设置布局文件
super(context, R.layout.view_marker);
this.companies = companies;
contentView = findViewById(R.id.content);
}
@Override
public void refreshContent(Entry e, Highlight highlight) {
Company item = companies.get((int) e.getX());
contentView.setText(item.getProvince() + "\n"+ "企业数量:" + item.getCount());
super.refreshContent(e, highlight);
}
// 设置偏移量
@Override
public MPPointF getOffset() {
return new MPPointF(-(float) (getWidth() / 2), -getHeight() - 10);
}
}
好了,看一下最终的实现:
img 6
大功告成!
总结
MPAndroidChart 是一个功能非常丰富的 Chart 组件,基本可以满足你工作中的任何需求。这个示例只是它的冰山一角,还有更多实用的功能,等着我们慢慢探索。不过从示例中你也可以看得出,它的定制化还是需要我们费一番功夫的。万事开头难,但我认为这篇文章是一个好的开始。了解了示例中的基本配置后,就算是入门了。
附:我基于 MPAndroidChart 实现的一些 Chart :
img 7
网友评论