如何使用MPAndroidChart创建带有分组条的条形图?

27

如何使用MPAndroidChartBarChart比较两组数据?以下是应该展示出来的图片:enter image description here

我编辑了从Github上一个示例项目中得到的代码,如何将100f和110f的值放在一个Xaxis标签下的Whole Number显示?

        Score score1 = new Score(100f, 0, "Whole Number");
        mRealm.copyToRealm(score1);
        Score score2 = new Score(110f, 0, "Whole Number");
        mRealm.copyToRealm(score2);
4个回答

27

由于BarData构造函数已更新,您需要使用以下代码:

BarChart barChart = (BarChart) view.findViewById(R.id.chart);
barChart.setDrawBarShadow(false);
barChart.setDrawValueAboveBar(true);
barChart.setDescription("");
barChart.setMaxVisibleValueCount(50);
barChart.setPinchZoom(false);
barChart.setDrawGridBackground(false);

XAxis xl = barChart.getXAxis();
xl.setGranularity(1f);
xl.setCenterAxisLabels(true);
xl.setValueFormatter(new AxisValueFormatter() {
    @Override
    public String getFormattedValue(float value, AxisBase axis) {
        return String.valueOf((int) value);
    }

    @Override
    public int getDecimalDigits() {
        return 0;
    }
});

YAxis leftAxis = barChart.getAxisLeft();
leftAxis.setValueFormatter(new AxisValueFormatter() {
    @Override
    public String getFormattedValue(float value, AxisBase axis) {
        return String.valueOf((int) value);
    }

    @Override
    public int getDecimalDigits() {
        return 0;
    }
});
leftAxis.setDrawGridLines(false);
leftAxis.setSpaceTop(30f);
leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true
barChart.getAxisRight().setEnabled(false);

//data
float groupSpace = 0.04f;
float barSpace = 0.02f; // x2 dataset
float barWidth = 0.46f; // x2 dataset
// (0.46 + 0.02) * 2 + 0.04 = 1.00 -> interval per "group"

int startYear = 1980;
int endYear = 1985;
List<BarEntry> yVals1 = new ArrayList<BarEntry>(); 
List<BarEntry> yVals2 = new ArrayList<BarEntry>();

for (int i = startYear; i < endYear; i++) {
    yVals1.add(new BarEntry(i, 0.4f));
    yVals2.add(new BarEntry(i, 0.7f));
}

BarDataSet set1, set2;
if (barChart.getData() != null && barChart.getData().getDataSetCount() > 0) {
    set1 = (BarDataSet)barChart.getData().getDataSetByIndex(0);
    set2 = (BarDataSet)barChart.getData().getDataSetByIndex(1);
    set1.setValues(yVals1);
    set2.setValues(yVals2);
    barChart.getData().notifyDataChanged();
    barChart.notifyDataSetChanged();
} else {
    // create 2 datasets with different types
    set1 = new BarDataSet(yVals1, "Company A");
    set1.setColor(Color.rgb(104, 241, 175));
    set2 = new BarDataSet(yVals2, "Company B");
    set2.setColor(Color.rgb(164, 228, 251));
    ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
    dataSets.add(set1);
    dataSets.add(set2);
    BarData data = new BarData(dataSets);
    barChart.setData(data);
}

barChart.getBarData().setBarWidth(barWidth);
barChart.getXAxis().setAxisMinValue(startYear);
barChart.groupBars(startYear, groupSpace, barSpace);
barChart.invalidate();

这就是它的外观:

Result


嗨,lidox,感谢您的回答。您节省了我的许多天。请问您能否帮我处理标签?我该如何将标签设置在中心位置,就像您的图像中显示的那样。我的标签从0索引开始,而不是居中显示。提前致谢。 - Devraj
“每组间隔”解释让我节省了很多时间。谢谢。 - Simon
我的列表有21个数据,但只显示了7个,你能帮我解决一下吗? - MustafaShaikh

22

是的,这可以很容易地实现。

您需要一个带有多个BarDataSetsBarChart,其中每个数据集(在您的情况下)代表一种性别(男性或女性)。

示例代码(不包括 realm.io)

    List<String> xValues = ...; // "Denmark", "Finland", ...

    XAxis xAxis = chart.getXAxis();
    xAxis.setValueFormatter(new MyValueFormatter(xValues));

    // create 2 datasets 
    BarDataSet set1 = new BarDataSet(valuesMen, "Men");
    set1.setColor(Color.BLUE);
    BarDataSet set2 = new BarDataSet(valuesWomen, "Women");
    set2.setColor(Color.RED);

    BarData data = new BarData(set1, set2);
    chart.setData(data);
    chart.groupBars(...); // available since release v3.0.0
    chart.invalidate(); // refresh

如果您需要进一步的帮助,这里有一篇关于分组BarChart的详细教程detailed tutorial,可在维基上找到。
如果您想要将值在BarChart中叠加显示,您需要创建一个堆积柱状图:Android Stacked Bars Chart

9
Phillipp 这个 BarData 的构造函数已经改变了!你需要更新你的代码! - lidox

19

我尝试过的大多数答案都存在问题,比如标签错位、不居中或条形图被隐藏在屏幕空间之外。经过一番尝试后,我终于有一个正常工作的 poc。

最后4行是最重要的。

    ArrayList<BarEntry> barEntries = new ArrayList<>();
    ArrayList<BarEntry> barEntries1 = new ArrayList<>();
    ArrayList<BarEntry> barEntries2 = new ArrayList<>();
    ArrayList<BarEntry> barEntries3 = new ArrayList<>();

    barEntries.add(new BarEntry(1,989.21f));
    barEntries.add(new BarEntry(2,420.22f));
    barEntries.add(new BarEntry(3,758));
    barEntries.add(new BarEntry(4,3078.97f));
    barEntries.add(new BarEntry(5,14586.96f));
    barEntries.add(new BarEntry(6,400.4f));
    barEntries.add(new BarEntry(7,5888.58f));

    barEntries1.add(new BarEntry(1,950));
    barEntries1.add(new BarEntry(2,791));
    barEntries1.add(new BarEntry(3,630));
    barEntries1.add(new BarEntry(4,782));
    barEntries1.add(new BarEntry(5,2714.54f));
    barEntries1.add(new BarEntry(6,500));
    barEntries1.add(new BarEntry(7,2173.36f));

    barEntries2.add(new BarEntry(1,900));
    barEntries2.add(new BarEntry(2,691));
    barEntries2.add(new BarEntry(3,1030));
    barEntries2.add(new BarEntry(4,382));
    barEntries2.add(new BarEntry(5,2714f));
    barEntries2.add(new BarEntry(6,5000));
    barEntries2.add(new BarEntry(7,1173f));

    barEntries3.add(new BarEntry(1,200));
    barEntries3.add(new BarEntry(2,991));
    barEntries3.add(new BarEntry(3,1830));
    barEntries3.add(new BarEntry(4,3082));
    barEntries3.add(new BarEntry(5,214));
    barEntries3.add(new BarEntry(6,5600));
    barEntries3.add(new BarEntry(7,9173));

    BarDataSet barDataSet = new BarDataSet(barEntries,"DATA SET 1");
    barDataSet.setColor(Color.parseColor("#F44336"));
    BarDataSet barDataSet1 = new BarDataSet(barEntries1,"DATA SET 2");
    barDataSet1.setColors(Color.parseColor("#9C27B0"));
    BarDataSet barDataSet2 = new BarDataSet(barEntries2,"DATA SET 3");
    barDataSet1.setColors(Color.parseColor("#e241f4"));
    BarDataSet barDataSet3 = new BarDataSet(barEntries3,"DATA SET 4");
    barDataSet1.setColors(Color.parseColor("#42f46e"));

    String[] months = new String[] {"TYPE 1", "TYPE 2", "TYPE 3", "TYPE 4"};
    BarData data = new BarData(barDataSet,barDataSet1,barDataSet2,barDataSet3);
    barChart.setData(data);

    XAxis xAxis = barChart.getXAxis();
    xAxis.setValueFormatter(new IndexAxisValueFormatter(months));
    barChart.getAxisLeft().setAxisMinimum(0);
    xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
    xAxis.setGranularity(1);
    xAxis.setCenterAxisLabels(true);
    xAxis.setGranularityEnabled(true);

    float barSpace = 0.02f;
    float groupSpace = 0.3f;
    int groupCount = 4;

    //IMPORTANT *****
    data.setBarWidth(0.15f);
    barChart.getXAxis().setAxisMinimum(0);
    barChart.getXAxis().setAxisMaximum(0 + barChart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount);
    barChart.groupBars(0, groupSpace, barSpace); // perform the "explicit" grouping
    //***** IMPORTANT

我得到的最终结果是:

固定标签的条形图


嗨,Sudesh,你能否更新答案并附上完整的代码? - Supriya kahalekar
我已经完成了一个概念验证(POC),并提供了源代码和apk文件,您可以检查github链接。 - Extremis II
请详细说明新的IndexAxisValueFormatter(months)是如何工作的?我不理解。X值与“月份”(Type1,type2等)对应的方式是什么? - Coding John
1
嗨,Sidesh,你有没有想法如何在用户单击类型1部分的任何位置时一起显示所有4个类型1值在标记窗口中? - Ashim Kansal
@sudesh,它显示了“BarData data = new BarData(barDataSet,barDataSet1,barDataSet2,barDataSet3);”的类未找到异常警告。 - Sagar
@Sagar,可能是mpAndroidChart依赖项未被包含或者依赖项已更新。如果你仍然遇到问题,请检查我的示例项目是否适用于你 https://github.com/sudeshim3/GroupBarGraph,并告诉我是否有任何问题。 - Extremis II

2
  • 第一步 将柱状图的第一个数字分成几组。像下面的示例代码一样显示5组。每个组中有5个柱子。

               xaxis0 = new ArrayList<>();
               for (int i = 0; i < cData.size(); i++) {
    
                   String str = cData.get(i).get("count");
                   str = str.replaceAll("\\[", "").replaceAll("\\]", "");
                   String[] finalString = str.split(",");
                   if (i == 0) {
                       for (int k = 0; k < finalString.length; k++) {
    
                           int data22 = Integer.parseInt(finalString[k]);
                           BarEntry v1e1 = new BarEntry(data22, position);
                           valueSet1.add(v1e1);
                       }
                   }
                   if (i == 1) {
                       for (int k = 0; k < finalString.length; k++) {
                           int data22 = Integer.parseInt(finalString[k] + "");
                           BarEntry v1e1 = new BarEntry(data22, position);
                           valueSet2.add(v1e1);
                       }
                   }
                   if (i == 2) {
                       for (int k = 0; k < finalString.length; k++) {
                           int data22 = Integer.parseInt(finalString[k] + "");
                           BarEntry v1e1 = new BarEntry(data22, position);
                           valueSet3.add(v1e1);
                       }
                   }
                   if (i == 3) {
                       for (int k = 0; k < finalString.length; k++) {
                           int data22 = Integer.parseInt(finalString[k] + "");
                           BarEntry v1e1 = new BarEntry(data22, position);
                           valueSet4.add(v1e1);
                       }
                   }
                   if (i == 4) {
                       for (int k = 0; k < finalString.length; k++) {
                           int data22 = Integer.parseInt(finalString[k] + "");
                           BarEntry v1e1 = new BarEntry(data22, position);
                           valueSet5.add(v1e1);
                       }
                   }
                   xaxis0.add(i, xdata.get(i).get("date"));
    
  • 第二步 在上面的代码中,你可以观察到5组柱状图条目在每个valueset的循环中加载数据 - ArrayList valueSet2 = new ArrayList<>(); 在此之前进行初始化

  • 第三步 将这5组加载到Bardataset中,如下所示

    ` BarDataSet barDataSet1 = new BarDataSet(valueSet1, "Set1"); barDataSet1.setColors(whitecolors); barDataSet1.setValueTextColor(Color.WHITE);

    BarDataSet barDataSet2 = new BarDataSet(valueSet2, "Set2"); barDataSet2.setColors(whitecolors); barDataSet2.setValueTextColor(Color.WHITE);

    BarDataSet barDataSet3 = new BarDataSet(valueSet3, "Set3"); barDataSet3.setColors(whitecolors);

    barDataSet3.setValueTextColor(Color.WHITE); BarDataSet barDataSet4 = new BarDataSet(valueSet4, "Set4");

    barDataSet4.setColors(whitecolors); barDataSet4.setValueTextColor(Color.WHITE);

    BarDataSet barDataSet5 = new BarDataSet(valueSet5, "Set5"); barDataSet5.setColors(whitecolors);

    barDataSet5.setValueTextColor(Color.WHITE); dataSets = new ArrayList<>(); dataSets.add(barDataSet1); dataSets.add(barDataSet2); dataSets.add(barDataSet3); dataSets.add(barDataSet4); dataSets.add(barDataSet5); `

  • 最后一步需要将这些数据附加到Bardata中,如下所示的代码

BarData data11 = new BarData(xaxis0, dataSets); data11.setGroupSpace(100f);

BarData data11 = new BarData(x轴数据0, 数据集); data11.setGroupSpace(100f);

               holder.chart.setData(data11);

               XAxis xAxis = holder.chart.getXAxis();

               xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);

               xAxis.setDrawGridLines(true);  

xAxis.setGridColor(context.getResources().getColor(R.color.white));

               xAxis.isDrawLabelsEnabled();    

xAxis.setAxisLineColor(context.getResources().getColor(R.color.accentColor)); xAxis.setTextColor(context.getResources().getColor(R.color.white));
               xAxis.isAdjustXLabelsEnabled();

               xAxis.setAdjustXLabels(true);

               holder.chart.setDescription("");

               holder.chart.animateXY(2000, 2000);
 holder.chart.getAxisLeft().setTextColor(context.getResources().getColor(R.color.white));
               holder.chart.getAxisRight().setTextColor(context.getResources().getColor(R.color.white));
               holder.chart.setDrawGridBackground(false);
               holder.chart.getAxisRight().setEnabled(false);
               holder.chart.setDrawValueAboveBar(true);
               holder.chart.getAxisLeft().setEnabled(false);
               holder.chart.setSoundEffectsEnabled(true);
               holder.chart.getXAxis().setDrawGridLines(false);
               holder.chart.setTransitionGroup(true);
               YAxis yAxis = holder.chart.getAxisLeft();
               yAxis.setDrawGridLines(false);
               yAxis.setLabelCount(5);
               yAxis = holder.chart.getAxisRight();
               yAxis.setDrawGridLines(false);
               yAxis.setTextColor(context.getResources().getColor(R.color.white));
               Legend l =  holder.chart.getLegend();
               l.setEnabled(false);     
               Paint p = holder.chart.getPaint(Chart.PAINT_INFO);
               p.setTextSize(10);
               p.setColor(context.getResources().getColor(R.color.white));
               p.setTypeface(gotham);
               holder.chart.invalidate();
               l.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER);
               l.setTextSize(200);
               yAxis.setValueFormatter(new LargeValueFormatter());

   # Thats it if you have doubt about this code ask me any time .......

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接