1 前言
本篇文章主要描述MPAndroidChart中柱状图的一些例子,如堆叠图,重叠图,多柱图,正负柱图,这里不介绍BarChart的基本属性,因为在上一部分已经讲解,在上一篇文章基本都全部有介绍,有属性不了解的读者建议转到:安卓图形之MPAndroidChart3.0详解三——柱状图(一)(属性篇)
2 Demo
2.1 堆叠图
效果图如下:
完整代码如下:
xml代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/bc"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Java代码:
public class BarTest extends Fragment {
private BarChart bc;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.bar_frag,null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bc = view.findViewById(R.id.bc);
setDesc();
setLegend();
setXAxis();
setYAxis();
loadData();
}
//设置Title
private void setDesc() {
Description description = bc.getDescription();
// 获取屏幕中间x 轴的像素坐标
WindowManager wm=(WindowManager)getActivity().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
float x = dm.widthPixels / 2;
description.setPosition(x,50);
description.setText("年龄群体车辆违章的占比统计");
description.setTextSize(16f);
description.setTextColor(Color.BLACK);
bc.setDescription(description);
}
//设置图例
private void setLegend() {
Legend legend = bc.getLegend();
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
legend.setDrawInside(true);
legend.setTextSize(14f);
legend.setTypeface(Typeface.DEFAULT_BOLD);
legend.setXOffset(30);
legend.setOrientation(Legend.LegendOrientation.VERTICAL);
legend.setTypeface(Typeface.DEFAULT_BOLD);
}
//设置Y轴
private void setYAxis() {
bc.getAxisRight().setEnabled(false);
YAxis yAxis = bc.getAxisLeft();
yAxis.setTextSize(14f);
yAxis.setTextColor(Color.BLACK);
yAxis.setXOffset(15);
yAxis.setAxisMaximum(1200);
yAxis.setAxisMinimum(0);
yAxis.setGranularity(200f);
yAxis.setLabelCount(7);
}
//设置X轴
private void setXAxis() {
XAxis xAxis = bc.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextSize(16f);
xAxis.setTypeface(Typeface.DEFAULT_BOLD);
xAxis.setDrawGridLines(false);
xAxis.setLabelCount(5);
xAxis.setAxisMaximum(4.3f);
xAxis.setAxisMinimum(-0.3f);
xAxis.setGranularity(1f);
//自定义格式
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
int tep = (int) (9 - value);
return tep + "0后";
}
});
}
//设置数据
private void loadData() {
bc.setExtraOffsets(30,70,30,50);
bc.setTouchEnabled(false);
bc.animateXY(1000,1000);
final float d_1[] = {230f, 480f, 480f, 480f,170f};
final float d_2[] = { 120f,600f, 400f, 200f,80f};
List<BarEntry> entries = new ArrayList<BarEntry>();
for(int i = 0; i < d_1.length; i++){
//使用BarEntry的构造方法的第三个参数来保存需要在柱块上显示的数据
entries.add(new BarEntry(i,new float[]{d_1[i],d_2[i]},(d_2[i] / (d_1[i] + d_2[i])) * 100));
}
BarDataSet barDataSet = new BarDataSet(entries,"");
barDataSet.setColors(Color.parseColor("#6D9C00"),Color.parseColor("#F07408"));
barDataSet.setStackLabels(new String[]{"无违章","有违章"});
barDataSet.setValueTextColor(Color.RED);
BarData barData = new BarData(barDataSet);
barData.setBarWidth(0.3f);
//自定义格式
barData.setValueFormatter(new IValueFormatter() {
private int isY = -1;//用于判断是有违章还是无违章的柱块
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
isY ++;
if(isY %2 ==0){//无违章,则不显示文本
return "";
}else{//有违章,显示在entry中保存的数据
float res = (float) entry.getData();
return String.format("%.1f",res) + "%";
}
}
});
bc.setData(barData);
}
}
2.2 重叠图
重叠图与堆叠图的区别:
堆叠图是在一个柱块的基础上绘制下一个柱块,即在头上绘制
重叠图是两个柱块重叠在一个,都是在同一起点绘制的,后绘制的会覆盖先绘制的
效果图:
完整代码如下(xml代码不变):
public class BarTest_1 extends Fragment {
private BarChart bc;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.bar_frag,null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bc = view.findViewById(R.id.bc);
setDesc();
setLegend();
setXAxis();
setYAxis();
loadData();
}
//设置Title
private void setDesc() {
Description description = bc.getDescription();
// 获取屏幕中间x 轴的像素坐标
WindowManager wm=(WindowManager)getActivity().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
float x = dm.widthPixels / 2;
description.setPosition(x,50);
description.setText("年龄群体车辆违章的占比统计");
description.setTextSize(16f);
description.setTextColor(Color.BLACK);
bc.setDescription(description);
}
//设置图例
private void setLegend() {
Legend legend = bc.getLegend();
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
legend.setDrawInside(true);
legend.setTextSize(14f);
legend.setTypeface(Typeface.DEFAULT_BOLD);
legend.setXOffset(30);
legend.setOrientation(Legend.LegendOrientation.VERTICAL);
legend.setTypeface(Typeface.DEFAULT_BOLD);
}
//设置Y轴
private void setYAxis() {
bc.getAxisRight().setEnabled(false);
YAxis yAxis = bc.getAxisLeft();
yAxis.setTextSize(14f);
yAxis.setTextColor(Color.BLACK);
yAxis.setXOffset(15);
yAxis.setAxisMaximum(1200);
yAxis.setAxisMinimum(0);
yAxis.setGranularity(200f);
yAxis.setLabelCount(7);
}
//设置X轴
private void setXAxis() {
XAxis xAxis = bc.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextSize(16f);
xAxis.setTypeface(Typeface.DEFAULT_BOLD);
xAxis.setDrawGridLines(false);
xAxis.setLabelCount(5);
xAxis.setAxisMaximum(4.3f);
xAxis.setAxisMinimum(-0.3f);
xAxis.setGranularity(1f);
//自定义格式
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
int tep = (int) (9 - value);
return tep + "0后";
}
});
}
//设置数据
private void loadData() {
bc.setExtraOffsets(30,70,30,50);
bc.animateXY(1000,1000);
final float d_1[] = {230f, 480f, 480f, 480f,170f};
final float d_2[] = { 120f,600f, 400f, 200f,80f};
List<BarEntry> entries = new ArrayList<BarEntry>();
List<BarEntry> entries1 = new ArrayList<BarEntry>();
for(int i = 0; i < d_1.length; i++){
entries.add(new BarEntry(i,d_1[i]));
//使用BarEntry的构造方法的第三个参数来保存需要在柱块上显示的数据
entries1.add(new BarEntry(i,d_2[i] + d_1[i],(d_2[i] / (d_1[i] + d_2[i])) * 100));
}
BarDataSet barDataSet = new BarDataSet(entries,"无违章");
BarDataSet barDataSet1 = new BarDataSet(entries1,"有违章");
barDataSet.setColor(Color.parseColor("#6D9C00"));
barDataSet.setDrawValues(false);//不绘制文本
barDataSet1.setColor(Color.parseColor("#F07408"));
barDataSet1.setValueTextColor(Color.RED);
barDataSet1.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
//获取entry中的数据
float res = (float) entry.getData();
return String.format("%.1f",res) + "%";
}
});
BarData barData = new BarData(barDataSet1,barDataSet);
barData.setBarWidth(0.3f);//设置柱块的宽度
bc.setData(barData);
}
}
2.3 多柱图
多柱图主要通过barChart的属性groupBars设置,使用方法见代码
完整代码如下(xml代码不变):
public class BarTest_2 extends Fragment {
private BarChart bc;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.bar_frag,null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bc = view.findViewById(R.id.bc);
setDesc();
setLegend();
setXAxis();
setYAxis();
loadData();
}
//设置Title
private void setDesc() {
Description description = bc.getDescription();
// 获取屏幕中间x 轴的像素坐标
WindowManager wm=(WindowManager)getActivity().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
float x = dm.widthPixels / 2;
description.setPosition(x,50);
description.setText("年龄群体车辆违章的占比统计");
description.setTextSize(16f);
description.setTextColor(Color.BLACK);
bc.setDescription(description);
}
//设置图例
private void setLegend() {
Legend legend = bc.getLegend();
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
legend.setDrawInside(true);
legend.setTextSize(14f);
legend.setTypeface(Typeface.DEFAULT_BOLD);
legend.setXOffset(30);
legend.setOrientation(Legend.LegendOrientation.VERTICAL);
legend.setTypeface(Typeface.DEFAULT_BOLD);
}
//设置Y轴
private void setYAxis() {
bc.getAxisRight().setEnabled(false);
YAxis yAxis = bc.getAxisLeft();
yAxis.setTextSize(14f);
yAxis.setTextColor(Color.BLACK);
yAxis.setXOffset(15);
yAxis.setAxisMaximum(800);
yAxis.setAxisMinimum(0);
yAxis.setGranularity(200f);
yAxis.setLabelCount(7);
}
//设置X轴
private void setXAxis() {
XAxis xAxis = bc.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextSize(16f);
xAxis.setTypeface(Typeface.DEFAULT_BOLD);
xAxis.setDrawGridLines(false);
xAxis.setLabelCount(5);
xAxis.setAxisMaximum(4.3f);
xAxis.setAxisMinimum(-0.3f);
xAxis.setGranularity(1f);
//自定义格式
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
int tep = (int) (9 - value);
return tep + "0后";
}
});
}
//设置数据
private void loadData() {
bc.setExtraOffsets(30,70,30,50);
bc.animateXY(1000,1000);
bc.setFitBars(true);
final float d_1[] = {230f, 480f, 480f, 480f,170f};
final float d_2[] = { 120f,600f, 400f, 200f,80f};
List<BarEntry> entries = new ArrayList<BarEntry>();
List<BarEntry> entries1 = new ArrayList<BarEntry>();
for(int i = 0; i < d_1.length; i++){
//使用BarEntry的构造方法的第三个参数来保存需要在柱块上显示的数据
entries.add(new BarEntry(i,d_1[i],(d_1[i] / (d_1[i] + d_2[i])) * 100));
entries1.add(new BarEntry(i,d_2[i],(d_2[i] / (d_1[i] + d_2[i])) * 100));
}
BarDataSet barDataSet = new BarDataSet(entries,"无违章");
BarDataSet barDataSet1 = new BarDataSet(entries1,"有违章");
barDataSet.setColor(Color.parseColor("#6D9C00"));
barDataSet.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
//获取entry中的数据
float res = (float) entry.getData();
return String.format("%.1f",res) + "%";
}
});
barDataSet1.setColor(Color.parseColor("#F07408"));
barDataSet1.setValueTextColor(Color.RED);
barDataSet1.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
//获取entry中的数据
float res = (float) entry.getData();
return String.format("%.1f",res) + "%";
}
});
List<IBarDataSet> barDataSets = new ArrayList<IBarDataSet>();
barDataSets.add(barDataSet);
barDataSets.add(barDataSet1);
BarData barData = new BarData(barDataSets);
barData.setBarWidth(0.3f);//设置柱块的宽度
//参数1:距左边的距离(开始会偏移一个组的距离)
//参数二:组与组之间的间距
//参数三:一组柱块之中每个之间的距离
barData.groupBars(-0.35f,0.35f,0);
bc.setData(barData);
}
}
2.4 正负柱图
正负柱图其实实现起来非常简单,只要你的数据是负的,它就是向下面的,不过得你设置Y轴的最小值必须为负数,不然是看不到i下面的柱块的。
注意添加数据的方式为:entries.add(new BarEntry(i,new float[]{ 数据1 , 数据2 })),如果使用两个BarDataSet,然后把两个BarDataSet给BarData的话,出现的效果是两个BarDataSet中的数据相减后出现的柱块
效果图:
完整代码如下(xml代码不变):
public class BarTest_3 extends Fragment {
private BarChart bc;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.bar_frag,null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
bc = view.findViewById(R.id.bc);
setDesc();
setLegend();
setXAxis();
setYAxis();
loadData();
}
//设置Title
private void setDesc() {
Description description = bc.getDescription();
// 获取屏幕中间x 轴的像素坐标
WindowManager wm=(WindowManager)getActivity().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
float x = dm.widthPixels / 2;
description.setPosition(x,50);
description.setText("年龄群体车辆违章的占比统计");
description.setTextSize(16f);
description.setTextColor(Color.BLACK);
bc.setDescription(description);
}
//设置图例
private void setLegend() {
Legend legend = bc.getLegend();
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
legend.setDrawInside(true);
legend.setTextSize(14f);
legend.setTypeface(Typeface.DEFAULT_BOLD);
legend.setXOffset(30);
legend.setOrientation(Legend.LegendOrientation.VERTICAL);
legend.setTypeface(Typeface.DEFAULT_BOLD);
}
//设置Y轴
private void setYAxis() {
bc.getAxisRight().setEnabled(false);
YAxis yAxis = bc.getAxisLeft();
yAxis.setTextSize(14f);
yAxis.setTextColor(Color.BLACK);
yAxis.setXOffset(15);
yAxis.setAxisMaximum(800);
yAxis.setAxisMinimum(-800);//注意最小值为-800
}
//设置X轴
private void setXAxis() {
XAxis xAxis = bc.getXAxis();
xAxis.setEnabled(false);
}
//设置数据
private void loadData() {
bc.setExtraOffsets(30,70,30,50);
bc.animateXY(1000,1000);
bc.setFitBars(true);
final float d_1[] = {230f, 480f, 480f, 480f,170f};
final float d_2[] = { -120f,-600f, -400f, -200f,-80f};
List<BarEntry> entries = new ArrayList<BarEntry>();
for(int i = 0; i < d_1.length; i++){
entries.add(new BarEntry(i,new float[]{d_1[i],d_2[i]}));
}
BarDataSet barDataSet = new BarDataSet(entries,"");
// BarDataSet barDataSet1 = new BarDataSet(entries1,"有违章");
barDataSet.setStackLabels(new String[]{"无违章","有违章"});
barDataSet.setColors(Color.parseColor("#6D9C00"),Color.parseColor("#F07408"));
BarData barData = new BarData(barDataSet);
barData.setBarWidth(0.3f);//设置柱块的宽度
bc.setData(barData);
}
}