昨天在比赛中遇到了MP的并列柱状图,看网上对这方面记录并不是很多,所以今天就做一个教程吧。
先看简单的需求草图吧
好了,现在开始上代码,需要特别注意的地方,会重点标出来提醒。
public class Main2Activity extends AppCompatActivity { private BarChart chart; private CountDownTimer count; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); chart=findViewById(R.id.chart); info(); count=new CountDownTimer(Integer.MAX_VALUE,2000) { @Override public void onTick(long millisUntilFinished) { setData(); } @Override public void onFinish() { } }.start(); } private void info(){ XAxis xAxis=chart.getXAxis(); xAxis.setDrawGridLines(false); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setLabelCount(5); //设置x轴最小值 xAxis.setAxisMinimum(0f); //设置x轴最大值 xAxis.setAxisMaximum(5f); final String[] data={"周一","周二","周三","周四","周五"}; //标签居中 xAxis.setTextSize(25f); xAxis.setCenterAxisLabels(true); //自定义x轴 xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float v, AxisBase axisBase) { return data[(int) Math.abs(v%5)]; } }); YAxis left=chart.getAxisLeft(); left.setAxisMinimum(0f); left.setAxisMaximum(6f); left.setLabelCount(6); //设置字体大小 left.setTextSize(25f); //设置y轴左侧竖线宽度 不设置在自定义标签时会出现不显示竖线的情况 left.setAxisLineWidth(1f); //隐藏Y轴左侧网格线 left.setDrawGridLines(false); final String[] setY={"","畅通","缓行","拥堵","一般拥堵","严重拥堵"}; left.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float v, AxisBase axisBase) { return v>=6?"":setY[(int) v]; } }); YAxis right=chart.getAxisRight(); right.setDrawGridLines(false); right.setAxisMinimum(0f); right.setTextSize(25f); right.setAxisMaximum(5f); //设置图表编译,避免x轴标签显示不全 chart.setExtraBottomOffset(10); //禁用图例 chart.getLegend().setEnabled(false); //禁用描述 chart.getDescription().setEnabled(false); } private void setData(){ List<BarEntry> list1=new ArrayList<>(); List<BarEntry> list2=new ArrayList<>(); List<BarEntry> list3=new ArrayList<>(); for (int i=0;i<5;i++){ list1.add(new BarEntry(i, (float) (Math.random()*5))); list2.add(new BarEntry(i, (float) (Math.random()*5))); list3.add(new BarEntry(i, (float) (Math.random()*5))); } BarDataSet set1=new BarDataSet(list1,""); BarDataSet set2=new BarDataSet(list2,""); BarDataSet set3=new BarDataSet(list3,""); set1.setColor(Color.RED); set2.setColor(Color.BLUE); set3.setColor(Color.GREEN); BarData data=new BarData(set1,set2,set3); //组内柱状图之间的空间 float barspace=0.05f; //每组之间的空间 float groupspcae=0.3f; //柱状图的宽度 float barWidth=(1-0.3f-0.05f*3)/3; //设置柱状图的宽度 data.setBarWidth(barWidth); //(起始点,组间隔,组内间隔) data.groupBars(0f,groupspcae,barspace); //上面的计算公式为 图组间隔+(柱状图间隔*柱状图个数)+子柱状图宽度*每组柱状图个数=1f //简单计算为 子柱状图宽度=(1f-图组间隔-(柱状图间隔*柱状图个数))/每组柱状图个数 //设置 chart.setData(data); //刷新布局 chart.invalidate(); } @Override protected void onDestroy() { super.onDestroy(); if (count != null) { count.cancel(); count=null; } } }
看看实际效果图
现在,我们来实现如何点击隐藏相应的条目。
思路是这样的,这里感谢我的工作室同学,简单又粗暴:
点击相应的按钮,设置相应的柱状图颜色为白色。算一种比较投巧的办法吧。
我当时的想法是,对数据进行保留,然后加上标记位,每次点击,将相应位置的数据改为0,然后刷新布局即可。但是总是List数据改了 ,图表刷新却直接将一组数据全删了,很是纳闷,试了一个上午,都没有找到原因。
如果你们谁有更好的想法,也欢迎说一下
以下细节需要注意:
背景色一定要改为白色,默认的那个背景色并不是纯白,网格线需要禁用,否则效果很是尴尬。
需要隐藏掉标签显示,否则柱状图颜色没了,标签还在,当然也可以通过自定义 标签的显示,将相对应的标签自定义为“”,也可以实现禁用。
4.17号补充,直接更改数据然后刷新布局也可以实现,当时的改错了一个值。
下面开始上代码
public class Main2Activity extends AppCompatActivity implements View.OnClickListener { private BarChart chart; private CountDownTimer count; private BarDataSet set1; private BarDataSet set2; private BarDataSet set3; //标记位 private boolean mode1 = false, mode2 = false, mode3 = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); chart = findViewById(R.id.chart); info(); //定时器 count = new CountDownTimer(Integer.MAX_VALUE, 2000) { @Override public void onTick(long millisUntilFinished) { setData(); } @Override public void onFinish() { } }.start(); } private void info() { XAxis xAxis = chart.getXAxis(); xAxis.setDrawGridLines(false); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setLabelCount(5); //设置x轴最小值 xAxis.setAxisMinimum(0f); //设置x轴最大值 xAxis.setAxisMaximum(5f); final String[] data = {"周一", "周二", "周三", "周四", "周五"}; //标签居中 xAxis.setTextSize(25f); xAxis.setCenterAxisLabels(true); //自定义x轴 xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float v, AxisBase axisBase) { return data[(int) Math.abs(v % 5)]; } }); YAxis left = chart.getAxisLeft(); left.setAxisMinimum(0f); left.setAxisMaximum(6f); left.setLabelCount(6); //设置字体大小 left.setTextSize(25f); //设置y轴左侧竖线宽度 不设置在自定义标签时会出现不显示竖线的情况 left.setAxisLineWidth(1f); //隐藏Y轴左侧网格线 left.setDrawGridLines(false); final String[] setY = {"", "畅通", "缓行", "拥堵", "一般拥堵", "严重拥堵"}; left.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float v, AxisBase axisBase) { return v >= 6 ? "" : setY[(int) v]; } }); YAxis right = chart.getAxisRight(); right.setDrawGridLines(false); right.setAxisMinimum(0f); right.setTextSize(25f); right.setAxisMaximum(5f); //设置图表编译,避免x轴标签显示不全 chart.setExtraBottomOffset(10); //禁用图例 chart.getLegend().setEnabled(false); //禁用描述 chart.getDescription().setEnabled(false); chart.setBackgroundColor(Color.WHITE); findViewById(R.id.hide_red).setOnClickListener(this); findViewById(R.id.hide_blue).setOnClickListener(this); findViewById(R.id.hide_gre).setOnClickListener(this); } private void setData() { List<BarEntry> list1 = new ArrayList<>(); List<BarEntry> list2 = new ArrayList<>(); List<BarEntry> list3 = new ArrayList<>(); for (int i = 0; i < 5; i++) { list1.add(new BarEntry(i, (float) (Math.random() * 5))); list2.add(new BarEntry(i, (float) (Math.random() * 5))); list3.add(new BarEntry(i, (float) (Math.random() * 5))); } set1 = new BarDataSet(list1, ""); set2 = new BarDataSet(list2, ""); set3 = new BarDataSet(list3, ""); setHide(mode1, set1, Color.RED); setHide(mode2, set2, Color.BLUE); setHide(mode3, set3, Color.GREEN); BarData data = new BarData(set1, set2, set3); //组内柱状图之间的空间 float barspace = 0.05f; //每组之间的空间 float groupspcae = 0.3f; //柱状图的宽度 float barWidth = (1 - 0.3f - 0.05f * 3) / 3; //设置柱状图的宽度 data.setBarWidth(barWidth); //(起始点,组间隔,组内间隔) data.groupBars(0f, groupspcae, barspace); //上面的计算公式为 图组间隔+(柱状图间隔*柱状图个数)+子柱状图宽度*每组柱状图个数=1f //简单计算为 子柱状图宽度=(1f-图组间隔-(柱状图间隔*柱状图个数))/每组柱状图个数 //设置 chart.setData(data); //刷新布局 chart.invalidate(); } //设置柱状图颜色为白色 private void setHide(boolean mode, BarDataSet set, int color) { if (mode) { set.setColor(Color.WHITE); } else { set.setColor(color); } set.setDrawValues(false); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.hide_red: mode1 = true; set1.setColor(Color.WHITE); chart.invalidate(); break; case R.id.hide_blue: mode2 = true; set2.setColor(Color.WHITE); chart.invalidate(); break; case R.id.hide_gre: mode3 = true; set3.setColor(Color.WHITE); chart.invalidate(); break; } } @Override protected void onDestroy() { super.onDestroy(); if (count != null) { count.cancel(); count = null; } } }
效果就是这样。如果有更好的解决方案,也欢迎大家告诉我。