本章介绍了如何为各种图表设置数据。
折线图
如果要向图表添加值(数据),则必须通过:
public void setData(ChartData data) { ... }
基类ChartData类封装了在渲染期间图表所需的所有数据和信息。对于不同类型的图表,存在对应的ChartData子类(例如LineData)用于设置图表数据。在构造函数中,你可以提供一个List extends IDataSet>作为要显示的值。下面以LineData类(继承自ChartData)为示例,将数据添加到折线图:
/** List constructor */
public LineData(List sets) { ... }
/** Constructor with one or multiple ILineDataSet objects */
public LineData(ILineDataSet...) { ... }
那么,什么是DataSet,为什么你需要它?这实际上很简单。 一个DataSet对象表示图表中属于一起的一组条目(例如,Entry类)。 它用于在逻辑上分隔图表中不同的值组。不同类型的图表都有其对应的继承自DataSet的特定样式的子类对象(例如LineDataSet)。
例如,你可能希望在折线图中显示两个不同公司的一年的季度收入。在这种情况下,建议创建两个不同的LineDataSet对象,每个对象包含四个值(每个季度一个值)。也可以只提供一个LineDataSet对象,包含两个公司的所有8个值。
那么如何设置一个LineDataSet对象呢?
public LineDataSet(List entries, String label) { ... }
当查看构造函数(不同的构造函数都可用)时,可以看到,LineDataSet需要一个Entry类型的List和一个用来描述LineDataSet的String和一个用于图例的标签。此外,此标签可用于在LineData对象中的其他LineDataSet对象中查找LineDataSet。
Entry类型的列表封装了图表的所有值。 Entry对象是图表中具有x值和y值的条目附加的包装器:
public Entry(float x, float y) { ... }
综合考虑(两家公司季度收入超过一年的例子):
首先,创建将保存你的值的Entry类型的列表:
List valsComp1 = new ArrayList();
List valsComp2 = new ArrayList();
然后,使用Entry对象填充列表。 确保输入对象包含x轴的正确索引。(当然,这里可以使用循环,在这种情况下,循环的计数器变量可以是x轴上的索引)。
Entry c1e1 = new Entry(0f, 100000f); // 0 == quarter 1
valsComp1.add(c1e1);
Entry c1e2 = new Entry(1f, 140000f); // 1 == quarter 2 ...
valsComp1.add(c1e2);
// and so on ...
Entry c2e1 = new Entry(0f, 130000f); // 0 == quarter 1
valsComp2.add(c2e1);
Entry c2e2 = new Entry(1f, 115000f); // 1 == quarter 2 ...
valsComp2.add(c2e2);
//...
现在我们有了Entry对象的列表,可以创建LineDataSet对象:
LineDataSet setComp1 = new LineDataSet(valsComp1, "Company 1");
setComp1.setAxisDependency(AxisDependency.LEFT);
LineDataSet setComp2 = new LineDataSet(valsComp2, "Company 2");
setComp2.setAxisDependency(AxisDependency.LEFT);
通过调用Axis Dependency(...),指定DataSet应该绘制的轴。 最后,我们创建一个DataSet的列表并构建我们的ChartData对象:
// use the interface ILineDataSet
List dataSets = new ArrayList();
dataSets.add(setComp1);
dataSets.add(setComp2);
LineData data = new LineData(dataSets);
mLineChart.setData(data);
mLineChart.invalidate(); // refresh
调用invalidate()后,图表将刷新并绘制提供的数据。
如果我们要向x轴添加更多描述性值(而不是为不同季度在0到3之间的数字),我们可以使用Axis Value Formatter接口来实现。此接口允许在X轴上绘制自定义样式的值。 在此示例中,格式化程序可能如下所示:
// the labels that should be drawn on the XAxis
final String[] quarters = new String[] { "Q1", "Q2", "Q3", "Q4" };
IAxisValueFormatter formatter = new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return quarters[(int) value];
}
// we don't draw numbers, so no decimal digits needed
@Override
public int getDecimalDigits() { return 0; }
};
XAxis xAxis = mLineChart.getXAxis();
xAxis.setGranularity(1f); // minimum axis-step (interval) is 1
xAxis.setValueFormatter(formatter);
有关Axis Value Formatter接口的详细信息,请参见此处。
如果应用了附加样式,则此示例生成的折线图应类似于下面的示例:
一般BarChart,ScatterChart,BubbleChart和CandleStickChart的设置数据类似于LineChart。 一个特殊的情况是BarChart有多个(分组)条,这将在下面解释。
条目的顺序
请注意,此库不正式支持未按条目的x位置升序方式绘制折线图数据。以未排序的方式添加条目可能会正确绘图,但也可能出现意外。可以手动或使用条目比较器对条目对象列表进行排序:
List entries = ...;
Collections.sort(entries, new EntryXComparator());
这样做是因为使用二进制搜索算法可以更好地处理排序列表,性能更高。
饼图
与其他图表类型不同,饼图以PieEntry对象的形式获取数据。构造函数如下所示:
public PieEntry(float value, String label) { ... }
构造函数的第一个参数用于应该在饼图中绘制为饼形图的实际“值”。第二个参数“label”用于提供对切片的附加描述。
示例代码:
List entries = new ArrayList<>();
entries.add(new PieEntry(18.5f, "Green"));
entries.add(new PieEntry(26.7f, "Yellow"));
entries.add(new PieEntry(24.0f, "Red"));
entries.add(new PieEntry(30.8f, "Blue"));
PieDataSet set = new PieDataSet(entries, "Election Results");
PieData data = new PieData(set);
pieChart.setData(data);
pieChart.invalidate(); // refresh
PieEntry对象不保存x位置的值,因为图表中显示的PayEntry对象的顺序由它们在条目列表中的顺序确定。图标如下: