一:效果图
先看图解:
看图说话,多柱状图就是有多个DataSet,上面这个公式很重要,否则画出来的图简直是天马行空
完整代码
注释很详细,几乎每行代码都有注释
public class BarChartFragmnet extends BaseChart<BarChart> {
//DataSet 对应的Label
String[] arr = new String[]{
"Java",
"JavaWeb",
"python",
"php",
"C++",
};
//YAxis标签集
String[] leftXValue = new String[]{
"",
"simple",
"general",
"difficult",
"hell",
"Purgatory"
};
//XAxis数据
LinkedList<String> xValueList = new LinkedList<>();
@Override
protected BarChart createChart() {
return new BarChart(getContext());
}
@Override
protected void initData() {
//DataSet集合,这里多柱状图绘制,所有用这个集合保存DataSet
List<IBarDataSet> dataSets = new ArrayList<>();
for (int pos = 0; pos < 5; pos++) {
BarDataSet barDataSet = new BarDataSet(new ArrayList<BarEntry>(), arr[pos]);
//给柱子上色,ColorTemplate类是作者提供的颜色类,里面有一些长度为5的颜色数组,刚好我这是5个DataSet,一个DataSet对应一种颜色
barDataSet.setColor(ColorTemplate.JOYFUL_COLORS[pos]);
dataSets.add(barDataSet);
}
BarData barData = new BarData(dataSets);
//设置单挑柱状的在这个Group中的占比,也就是图解中的BarWidth
barData.setBarWidth(0.1f);
//获得左侧Y轴对象
YAxis axisLeft = mChart.getAxisLeft();
//设置y轴数据起始值为0
axisLeft.setAxisMinimum(0f);
//设置y轴标签的个数
axisLeft.setLabelCount(6);
//设置y轴粒度为1f,必须设置,意思就是y轴的Value一直累加1,由于在3.0.3版本中y轴Value值不是再是1,2,3,4这种一直累加,而是由框架自适应计算值
//便于后期自定义Y轴刻度数据
axisLeft.setGranularity(1f);
//设置y轴最大刻度值
axisLeft.setAxisMaximum(6f);
/**
* 格式化y轴数据,这里有个坑,不能直接new IAxisValueFormatter(),
* new IAxisValueFormatter() {
* @Override
* public String getFormattedValue(float value, AxisBase axis) {
* return null;
* }
* }
*
* getFormattedValue中有两参数,我们主要看Value,一开始我天真的以为这个Value就是0,1,2,3,4这样的Y轴刻度值,一顿操作,把这个Value当下标设置自定义Y轴数据
* 把程序跑起来,直接抛java.lang.ArrayIndexOutOfBoundsException ε=ε=ε=(~ ̄▽ ̄)~
* 打印出来发现这个值还能出现负数
* 后来在stackoverflow上找到下面这种方法,IndexAxisValueFormatter也是实现了IAxisValueFormatter,不过它对Value做了一些处理,、
* 配合setGranularity()一起使用即可实现在2.0的效果
*
*/
axisLeft.setValueFormatter(new IndexAxisValueFormatter(leftXValue));
//设置是否绘制Y轴网格线,
axisLeft.setDrawGridLines(false);
//设置是否绘制左侧y轴的线
//axisLeft.setDrawAxisLine(false);
//设置隐藏右侧轴线
mChart.getAxisRight().setEnabled(false);
//获得X轴线对象
XAxis xAxis = mChart.getXAxis();
//设置X轴轴线位于下方
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
//设置x轴刻度起始值为0f
xAxis.setAxisMinimum(0f);
//设置X轴粒度,和y轴同理
xAxis.setGranularity(1f);
//设置x轴刻度位于Group的中间
xAxis.setCenterAxisLabels(true);
//设置X轴数据倾斜度,负数为逆时针,正数为顺时针
//xAxis.setLabelRotationAngle(-60);
//获得图例说明对象
Legend legend = mChart.getLegend();
//设置图例说明位于柱状图下面的中间
legend.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER);
//绑定数据
mChart.setData(barData);
//模拟数据更新,没3.4秒调用updateChart(int[] arr)方法
timer.schedule(new TimerTask() {
@Override
public void run() {
//切换主线程便于更新图表
getActivity().runOnUiThread(() ->
updateChart(new int[]{
(random.nextInt(5) + 1),
(random.nextInt(5) + 1),
(random.nextInt(5) + 1),
(random.nextInt(5) + 1),
(random.nextInt(5) + 1)}));
}
}, 0, 3400);
}
public void updateChart(int[] arr) {
//循环给5个DataSet添加数据
for (int pos = 0, size = mChart.getBarData().getDataSetCount(); pos < size; pos++) {
//这里当EntryCount小于7时直接添加数据
if (mChart.getBarData().getDataSetByIndex(pos).getEntryCount() < 7) {
xValueList.add(mDateFormat.format(System.currentTimeMillis()));
mChart.getBarData().getDataSetByIndex(pos).addEntry(new BarEntry(mChart.getBarData().getDataSetByIndex(pos).getEntryCount(), arr[pos]));
}
//当EntryCount>=7是做删除和更新操作
else {
//删除x轴刻度数据第一个
xValueList.removeFirst();
//删除第一个Entry
mChart.getBarData().getDataSetByIndex(pos).removeEntry(0);
//删除后再做添加操作
xValueList.add(mDateFormat.format(System.currentTimeMillis()));
mChart.getBarData().getDataSetByIndex(pos).addEntry(new BarEntry(mChart.getBarData().getDataSetByIndex(pos).getEntryCount(), arr[pos]));
/**
* 精髓所在
* 遍历DataSet中所有Entry,将所有的Entry的x轴数据-1,实现更新图表的效果
*/
for (int index = 0, entrySize = mChart.getBarData().getDataSetByIndex(pos).getEntryCount(); index < entrySize; index++) {
float newX = mChart.getBarData().getDataSetByIndex(pos).getEntryForIndex(index).getX() - 1;
mChart.getBarData().getDataSetByIndex(pos).getEntryForIndex(index).setX(newX);
}
}
}
//动态更新x轴刻度自定义的数据
mChart.getXAxis().setValueFormatter(new IndexAxisValueFormatter(xValueList));
//以下两属性必须设置,而且必须每次更新都设置一遍
//设置图例上显示多少个柱子,这里是多柱状图,所以这里设置显示多少个组
mChart.setVisibleXRangeMinimum(7f);
mChart.setVisibleXRangeMaximum(7f);
//设置柱距和组距的占比,怎么算往上翻看图二图解
//更新一次设置一次
mChart.groupBars(0f, 0.2f, 0.06f);
//通知BarData更新
mChart.getBarData().notifyDataChanged();
//通知BarChart更新
mChart.notifyDataSetChanged();
//使图表更新生效
mChart.invalidate();
}
}
有什么疑问可以直接在底下私信我