Android Grouped Stacked Bar Chart Using MpChart Kotlin

In this tutorial we will use popular Chart library for Android (MpAndroidChart).

We will use BarChart View from MpChart Library.

We will write code which will result in below Graph.

Android Grouped and Stacked BarChart using MpChart Example

Steps:

  • Add Bar Chart View in XML Layout File.
  • Prepare X-Axis values and Labels for Chart Data.
  • Grouping –  Add multiple Bar Data Sets and group them to achieve Grouped Bar Data.
  • Stacked – Add Bar Entries in each Bar Data Set and Add them to achieve Stacked Bar Data.
  • Customize Legends in Chart. Add custom Legend Entries to override default legends.
  • Customize Bar Data Set and Bar entries to give different color to each Data Set.
  • Center X-Axis Labels and align them with Bar.
  • End Result of above steps will be Grouped Stacked Bar Chart/Graph. 

Setup Gradle Dependencies

implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'


repositories {
jcenter()
maven { url 'https://jitpack.io' }
}

Add Bar Chart in XML Layout File

<com.github.mikephil.charting.charts.BarChart
android:id="@+id/chartConsumptionGraph"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_margin="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

Implement Grouped Bar Chart 

var barChartView = findViewById<BarChart>(R.id.chartConsumptionGraph)

Define X-Axis Lables

var xAxisValues = ArrayList<String>()
xAxisValues.add("Jan")
xAxisValues.add("Feb")
xAxisValues.add("Mar")
xAxisValues.add("Apr")
xAxisValues.add("May")
xAxisValues.add("June")
xAxisValues.add("Jul")
xAxisValues.add("Aug")
xAxisValues.add("Sep")
xAxisValues.add("Oct")
xAxisValues.add("Nov")
xAxisValues.add("Dec")

Define and Prepare Y-Axis (Stacked Data)

  • As each Y-Axis Bar will represent 2 different values (Stack).
  • And each X-Axis will have 2 different Bar’s or Data Set (Group).
  • Combining both above will give us Grouped Stacked Bar Chart.

First argument in Bar Entry initialization represent X-Axis and Second value is to be used for Y-Axis Values. As we Need to add 2 values in each Bar Entry Y-Axis (Stack) and X-Axis (Grouped).
So the second argument will be array of Float values (Stack).

var yValueGroup1 = ArrayList<BarEntry>()
var yValueGroup2 = ArrayList<BarEntry>()


yValueGroup1.add(BarEntry(1f, floatArrayOf(9.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(1f, floatArrayOf(2.toFloat(), 7.toFloat())))


yValueGroup1.add(BarEntry(2f, floatArrayOf(3.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(2f, floatArrayOf(4.toFloat(), 15.toFloat())))

yValueGroup1.add(BarEntry(3f, floatArrayOf(3.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(3f, floatArrayOf(4.toFloat(), 15.toFloat())))

yValueGroup1.add(BarEntry(4f, floatArrayOf(3.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(4f, floatArrayOf(4.toFloat(), 15.toFloat())))


yValueGroup1.add(BarEntry(5f, floatArrayOf(9.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(5f, floatArrayOf(10.toFloat(), 6.toFloat())))

yValueGroup1.add(BarEntry(6f, floatArrayOf(11.toFloat(), 1.toFloat())))
yValueGroup2.add(BarEntry(6f, floatArrayOf(12.toFloat(), 2.toFloat())))


yValueGroup1.add(BarEntry(7f, floatArrayOf(11.toFloat(), 7.toFloat())))
yValueGroup2.add(BarEntry(7f, floatArrayOf(12.toFloat(), 12.toFloat())))


yValueGroup1.add(BarEntry(8f, floatArrayOf(11.toFloat(), 9.toFloat())))
yValueGroup2.add(BarEntry(8f, floatArrayOf(12.toFloat(), 8.toFloat())))


yValueGroup1.add(BarEntry(9f, floatArrayOf(11.toFloat(), 13.toFloat())))
yValueGroup2.add(BarEntry(9f, floatArrayOf(12.toFloat(), 12.toFloat())))

yValueGroup1.add(BarEntry(10f, floatArrayOf(11.toFloat(), 2.toFloat())))
yValueGroup2.add(BarEntry(10f, floatArrayOf(12.toFloat(), 7.toFloat())))

yValueGroup1.add(BarEntry(11f, floatArrayOf(11.toFloat(), 6.toFloat())))
yValueGroup2.add(BarEntry(11f, floatArrayOf(12.toFloat(), 5.toFloat())))

yValueGroup1.add(BarEntry(12f, floatArrayOf(11.toFloat(), 2.toFloat())))
yValueGroup2.add(BarEntry(12f, floatArrayOf(12.toFloat(), 3.toFloat())))

Prepare Group Data

For Group Data we will use BarDataSet Class from MpAndroidChart library.

var barDataSet1: BarDataSet
var barDataSet2: BarDataSet


barDataSet1 = BarDataSet(yValueGroup1, "")
barDataSet1.setColors(Color.BLUE, Color.RED)

barDataSet1.setDrawIcons(false)
barDataSet1.setDrawValues(false)

barDataSet2 = BarDataSet(yValueGroup2, "")
barDataSet2.setColors(Color.YELLOW, Color.RED)
barDataSet2.setDrawIcons(false)
barDataSet2.setDrawValues(false)


// Pass Both Bar Data Set's in Bar Data.
var barData = BarData(barDataSet1, barDataSet2)

barChartView.description.isEnabled = false
barChartView.description.textSize = 0f
barData.setValueFormatter(LargeValueFormatter())
barChartView.setData(barData)
barChartView.getBarData().setBarWidth(barWidth)
barChartView.getXAxis().setAxisMinimum(0f)
barChartView.getXAxis().setAxisMaximum(12f)
barChartView.groupBars(0f, groupSpace, barSpace)
// barChartView.setFitBars(true)
barChartView.getData().setHighlightEnabled(false)
barChartView.invalidate()

Customize Bar Chart Legends using Legend Entry

// set bar label
var legend = barChartView.legend
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM)
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT)
legend.setOrientation(Legend.LegendOrientation.HORIZONTAL)
legend.setDrawInside(false)

var legenedEntries = arrayListOf<LegendEntry>()

legenedEntries.add(LegendEntry("2016", Legend.LegendForm.SQUARE, 8f, 8f, null, Color.RED))
legenedEntries.add(LegendEntry("2017", Legend.LegendForm.SQUARE, 8f, 8f, null, Color.YELLOW))

legend.setCustom(legenedEntries)

legend.setYOffset(2f)
legend.setXOffset(2f)
legend.setYEntrySpace(0f)
legend.setTextSize(5f)


Populate X-Axis Data

val xAxis = barChartView.getXAxis()
xAxis.setGranularity(1f)
xAxis.setGranularityEnabled(true)
xAxis.setCenterAxisLabels(true)
xAxis.setDrawGridLines(false)
xAxis.textSize = 9f

xAxis.setPosition(XAxis.XAxisPosition.BOTTOM)
xAxis.setValueFormatter(IndexAxisValueFormatter(xAxisValues))

xAxis.setLabelCount(12)
xAxis.mAxisMaximum = 12f
xAxis.setCenterAxisLabels(true)
xAxis.setAvoidFirstLastClipping(true)
xAxis.spaceMin = 4f
xAxis.spaceMax = 4f

Modify Y-Axis

val leftAxis = barChartView.getAxisLeft()
leftAxis.setValueFormatter(LargeValueFormatter())
leftAxis.setDrawGridLines(false)
leftAxis.setSpaceTop(1f)
leftAxis.setAxisMinimum(0f)

barChartView.data = barData
barChartView.setVisibleXRange(1f, 12f)

Complete Code:

fun populateGraphData() {

var barChartView = findViewById<BarChart>(R.id.chartConsumptionGraph)

val barWidth: Float
val barSpace: Float
val groupSpace: Float
val groupCount = 12

barWidth = 0.15f
barSpace = 0.07f
groupSpace = 0.56f

var xAxisValues = ArrayList<String>()
xAxisValues.add("Jan")
xAxisValues.add("Feb")
xAxisValues.add("Mar")
xAxisValues.add("Apr")
xAxisValues.add("May")
xAxisValues.add("June")
xAxisValues.add("Jul")
xAxisValues.add("Aug")
xAxisValues.add("Sep")
xAxisValues.add("Oct")
xAxisValues.add("Nov")
xAxisValues.add("Dec")

var yValueGroup1 = ArrayList<BarEntry>()
var yValueGroup2 = ArrayList<BarEntry>()

// draw the graph
var barDataSet1: BarDataSet
var barDataSet2: BarDataSet


yValueGroup1.add(BarEntry(1f, floatArrayOf(9.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(1f, floatArrayOf(2.toFloat(), 7.toFloat())))


yValueGroup1.add(BarEntry(2f, floatArrayOf(3.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(2f, floatArrayOf(4.toFloat(), 15.toFloat())))

yValueGroup1.add(BarEntry(3f, floatArrayOf(3.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(3f, floatArrayOf(4.toFloat(), 15.toFloat())))

yValueGroup1.add(BarEntry(4f, floatArrayOf(3.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(4f, floatArrayOf(4.toFloat(), 15.toFloat())))


yValueGroup1.add(BarEntry(5f, floatArrayOf(9.toFloat(), 3.toFloat())))
yValueGroup2.add(BarEntry(5f, floatArrayOf(10.toFloat(), 6.toFloat())))

yValueGroup1.add(BarEntry(6f, floatArrayOf(11.toFloat(), 1.toFloat())))
yValueGroup2.add(BarEntry(6f, floatArrayOf(12.toFloat(), 2.toFloat())))


yValueGroup1.add(BarEntry(7f, floatArrayOf(11.toFloat(), 7.toFloat())))
yValueGroup2.add(BarEntry(7f, floatArrayOf(12.toFloat(), 12.toFloat())))


yValueGroup1.add(BarEntry(8f, floatArrayOf(11.toFloat(), 9.toFloat())))
yValueGroup2.add(BarEntry(8f, floatArrayOf(12.toFloat(), 8.toFloat())))


yValueGroup1.add(BarEntry(9f, floatArrayOf(11.toFloat(), 13.toFloat())))
yValueGroup2.add(BarEntry(9f, floatArrayOf(12.toFloat(), 12.toFloat())))

yValueGroup1.add(BarEntry(10f, floatArrayOf(11.toFloat(), 2.toFloat())))
yValueGroup2.add(BarEntry(10f, floatArrayOf(12.toFloat(), 7.toFloat())))

yValueGroup1.add(BarEntry(11f, floatArrayOf(11.toFloat(), 6.toFloat())))
yValueGroup2.add(BarEntry(11f, floatArrayOf(12.toFloat(), 5.toFloat())))

yValueGroup1.add(BarEntry(12f, floatArrayOf(11.toFloat(), 2.toFloat())))
yValueGroup2.add(BarEntry(12f, floatArrayOf(12.toFloat(), 3.toFloat())))


barDataSet1 = BarDataSet(yValueGroup1, "")
barDataSet1.setColors(Color.BLUE, Color.RED)
barDataSet1.label = "2016"
barDataSet1.setDrawIcons(false)
barDataSet1.setDrawValues(false)



barDataSet2 = BarDataSet(yValueGroup2, "")

barDataSet2.label = "2017"
barDataSet2.setColors(Color.YELLOW, Color.RED)

barDataSet2.setDrawIcons(false)
barDataSet2.setDrawValues(false)

var barData = BarData(barDataSet1, barDataSet2)

barChartView.description.isEnabled = false
barChartView.description.textSize = 0f
barData.setValueFormatter(LargeValueFormatter())
barChartView.setData(barData)
barChartView.getBarData().setBarWidth(barWidth)
barChartView.getXAxis().setAxisMinimum(0f)
barChartView.getXAxis().setAxisMaximum(12f)
barChartView.groupBars(0f, groupSpace, barSpace)
// barChartView.setFitBars(true)
barChartView.getData().setHighlightEnabled(false)
barChartView.invalidate()

// set bar label
var legend = barChartView.legend
legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM)
legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT)
legend.setOrientation(Legend.LegendOrientation.HORIZONTAL)
legend.setDrawInside(false)

var legenedEntries = arrayListOf<LegendEntry>()

legenedEntries.add(LegendEntry("2016", Legend.LegendForm.SQUARE, 8f, 8f, null, Color.RED))
legenedEntries.add(LegendEntry("2017", Legend.LegendForm.SQUARE, 8f, 8f, null, Color.YELLOW))

legend.setCustom(legenedEntries)

legend.setYOffset(2f)
legend.setXOffset(2f)
legend.setYEntrySpace(0f)
legend.setTextSize(5f)

val xAxis = barChartView.getXAxis()
xAxis.setGranularity(1f)
xAxis.setGranularityEnabled(true)
xAxis.setCenterAxisLabels(true)
xAxis.setDrawGridLines(false)
xAxis.textSize = 9f

xAxis.setPosition(XAxis.XAxisPosition.BOTTOM)
xAxis.setValueFormatter(IndexAxisValueFormatter(xAxisValues))

xAxis.setLabelCount(12)
xAxis.mAxisMaximum = 12f
xAxis.setCenterAxisLabels(true)
xAxis.setAvoidFirstLastClipping(true)
xAxis.spaceMin = 4f
xAxis.spaceMax = 4f

barChartView.setVisibleXRangeMaximum(12f)
barChartView.setVisibleXRangeMinimum(12f)
barChartView.setDragEnabled(true)

//Y-axis
barChartView.getAxisRight().setEnabled(false)
barChartView.setScaleEnabled(true)

val leftAxis = barChartView.getAxisLeft()
leftAxis.setValueFormatter(LargeValueFormatter())
leftAxis.setDrawGridLines(false)
leftAxis.setSpaceTop(1f)
leftAxis.setAxisMinimum(0f)


barChartView.data = barData
barChartView.setVisibleXRange(1f, 12f)
}

If you have any issue or confusion please write in comment below I will try my best to help you out.

Thank you 🙂

Copyright: http://developine.com/

Posts created 35

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top