MPAndroidChart攻略——BarChart并列柱状图的点点滴滴。
MPAndroidChart_折线图的那些事
MPAndroidChart_饼图的那些事
MPAndroidChart_动态柱状图
MPAndroidChart_水平条形图的那些事
MPAndroidChart_并列柱状图,及如何实现点击隐藏掉不需要的条目。
MPAndroidChart_雷达图的那些事及自定义标签颜色
昨天在比赛中遇到了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 list1=new ArrayList<>();
List list2=new ArrayList<>();
List 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 list1 = new ArrayList<>();
List list2 = new ArrayList<>();
List 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;
}
}
}
效果就是这样。如果有更好的解决方案,也欢迎大家告诉我。