Create modern multi barch chart using MPAndroidChart in android - android

I'm creating multi bar chart using MPAndroidChart library for android, but it's not as per our design requirement,
I can able to create like following image using following code
barChart.description.isEnabled = false
barChart.setPinchZoom(false)
barChart.setDrawBarShadow(false)
barChart.setDrawGridBackground(false)
val mv = MyMarkerView(context, R.layout.view_marker)
mv.chartView = barChart
barChart.marker = mv
val l: Legend = barChart.legend
l.isEnabled = false
barChart.setExtraOffsets(5f, 5f, 5f, 15f)
val xAxis: XAxis = barChart.xAxis
xAxis.granularity = 1f
xAxis.setCenterAxisLabels(true)
xAxis.position = XAxis.XAxisPosition.BOTTOM
val leftAxis: YAxis = barChart.axisLeft
leftAxis.valueFormatter = MyYAxisValueFormatter(barChart)
leftAxis.setDrawGridLines(false)
leftAxis.spaceTop = 35f
leftAxis.axisMinimum = 0f
barChart.axisRight.isEnabled = false
barChart.axisLeft.setDrawGridLines(false)
barChart.xAxis.setDrawGridLines(false)
and set data for bar char as per code below
val values1 = ArrayList<BarEntry>()
val values2 = ArrayList<BarEntry>()
for ((index, value) in dataList.withIndex()) {
values1.add(BarEntry((index).toFloat(), value.y1.toFloat()))
values2.add(BarEntry((index).toFloat(), value.y2.toFloat()))
}
Log.d("data", "sales: ${values1.size} / purchase: ${values2.size}")
val set1 = BarDataSet(values1, "Sales")
val set2 = BarDataSet(values2, "Purchase")
set1.color = colorSales
set2.color = colorPurchase
val data = BarData(set1, set2)
data.setValueFormatter(LargeValueFormatter())
data.setDrawValues(false)
barChart.data = data
val months = arrayOf("APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", "JAN", "FEB", "MAR")
barChart.xAxis.valueFormatter = IndexAxisValueFormatter(months)
val xAxis = barChart.xAxis
xAxis.valueFormatter = IndexAxisValueFormatter(months)
barChart.axisLeft.axisMinimum = 0f
xAxis.position = XAxis.XAxisPosition.BOTTOM
xAxis.granularity = 1f
xAxis.setCenterAxisLabels(true)
xAxis.isGranularityEnabled = true
val barSpace = 0.1f
val groupSpace = 0.3f
val groupCount = 12
data.barWidth = 0.2f
barChart.xAxis.axisMinimum = 0f
barChart.xAxis.axisMaximum = 0 + barChart.barData.getGroupWidth(groupSpace, barSpace) * groupCount
barChart.xAxis.xOffset = -10f
barChart.groupBars(0.7f, groupSpace, barSpace) // perform the "explicit" grouping
barChart.invalidate()
output of above code is chart below
but i want graph like below,
please help me on this if anyone has experience with using MPAndroidChart

You need to make xAxis.isGranularityEnabled = false
From the documentation:
* When true, axis labels are controlled by the granularity property.
* When false, axis values could possibly be repeated.
* This could happen if two adjacent axis values are rounded to same
value.
* If using granularity this could be avoided by having
fewer axis values visible

Related

MPAndroidChart plotting incorrect linear graph

Trying to implement mpandroidchart, but the graph is ending up useless because it is plotting the chart incorrectly.
Below is the snippet of how i try to implement.
fun setGraph(cdata : ArrayList<Entry>){
val lineChart: LineChart = bind.lineChartViewPage
lineChart.setExtraOffsets(0f, 40f, 0f, 40f)
lineChart.setDrawBorders(false)
lineChart.setDrawGridBackground(false)
lineChart.legend.isEnabled = false
lineChart.description.isEnabled = false
lineChart.setTouchEnabled(false)
lineChart.isDragEnabled = false
lineChart.setScaleEnabled(false)
lineChart.setPinchZoom(false)
lineChart.isAutoScaleMinMaxEnabled = false
val lds = LineDataSet(cdata, "my data")
lds.mode = LineDataSet.Mode.LINEAR
lds.setDrawCircleHole(false)
lds.setDrawCircles(false)
lds.color = Color.parseColor("#ffffff")
lds.lineWidth = 1.5f
lds.isHighlightEnabled = false
val lineDataSets: ArrayList<ILineDataSet> = ArrayList<ILineDataSet>()
lineDataSets.add(lds)
lds.setDrawValues(false)
val lineData = LineData(lineDataSets)
val ll1 = LimitLine(2.5F)
ll1.lineWidth = 2f
ll1.lineColor = Color.parseColor("#99ce7aff")
val yAxisRight: YAxis = lineChart.axisRight
yAxisRight.textColor = Color.WHITE
yAxisRight.setDrawZeroLine(false)
yAxisRight.setDrawAxisLine(false)
yAxisRight.setCenterAxisLabels(true)
yAxisRight.setDrawTopYLabelEntry(true)
yAxisRight.setDrawGridLines(false)
yAxisRight.setGranularity(1.0f)
yAxisRight.isGranularityEnabled = true
yAxisRight.setLabelCount(6, true)
yAxisRight.removeAllLimitLines()
yAxisRight.addLimitLine(ll1)
yAxisRight.axisMaximum = 3.0f
yAxisRight.axisMinimum = 0.0f
val xAxis: XAxis = lineChart.xAxis
xAxis.isEnabled = false
xAxis.valueFormatter = null
xAxis.setDrawLabels(false)
xAxis.setDrawGridLines(false)
val yAxisLeft: YAxis = lineChart.axisLeft
yAxisLeft.isEnabled = false
yAxisLeft.setDrawLabels(false)
yAxisLeft.setDrawGridLines(false)
// hide legend
val legend: Legend = lineChart.legend
legend.isEnabled = false
lineChart.data = lineData
lineChart.data.notifyDataChanged()
lineChart.notifyDataSetChanged()
lineChart.invalidate()
}
I tried out some combinations and found a different behavior if i comment out below lines :
yAxisRight.axisMaximum = 3.0f
yAxisRight.axisMinimum = 0.0f
Before commenting lines (incorrect plotting with limit line)
After commenting lines (correct plotting and limit line vanished)
Below is the dataset on which the graph is being plotted. here the max value is 0.8f and min value is 0.1f.
private fun fakeData():ArrayList<Entry>{
val al: ArrayList<Entry> = ArrayList()
al.add(Entry(1F, 0.2F))
al.add(Entry(2F, 0.4F))
al.add(Entry(3F, 0.5F))
al.add(Entry(4F, 0.6F))
al.add(Entry(5F, 0.3F))
al.add(Entry(6F, 0.4F))
al.add(Entry(7F, 0.6F))
al.add(Entry(8F, 0.7F))
al.add(Entry(9F, 0.4F))
al.add(Entry(10F, 0.1F))
al.add(Entry(11F, 0.3F))
al.add(Entry(12F, 0.3F))
al.add(Entry(13F, 0.5F))
al.add(Entry(14F, 0.6F))
al.add(Entry(15F, 0.47F))
al.add(Entry(16F, 0.55F))
al.add(Entry(17F, 0.66F))
al.add(Entry(18F, 0.45F))
al.add(Entry(19F, 0.46F))
al.add(Entry(20F, 0.33F))
al.add(Entry(21F, 0.4F))
al.add(Entry(22F, 0.36F))
al.add(Entry(23F, 0.37F))
al.add(Entry(24F, 0.46F))
al.add(Entry(25F, 0.74F))
al.add(Entry(26F, 0.76F))
al.add(Entry(27F, 0.79F))
al.add(Entry(28F, 0.8F))
return al
}
If i dont set min and max values as below; then the limit line won't show up.
yAxisRight.axisMaximum = 3.0f
yAxisRight.axisMinimum = 0.0f
chart version : com.github.PhilJay:MPAndroidChart:v3.1.0
Please let me know if there is something wrong with this implementation or possible ways to correct this.
UPDATE :
Tried multiple dataset and found that defining custom yaxis min and max value is causing the chart to be drawn incorrectly. I cant understand why?
Had the same issue and the fix is pretty easy, but not straightforward, though, you should set the same max and min values for both y-axises:
axisLeft.apply {
axisMinimum = 0.0f
axisMaximum = 3.0f
}
axisRight.apply {
axisMinimum = 0.0f
axisMaximum = 3.0f
}

MPAndroidChart x axis

I try to display some charts in my android app. I use MPAndroidChart library. But somehow my chart is always compress on the x-axis. The value seems to have all the x value 0.
In the data set this is not the case. I can not figure out what I am doing wrong.
val chart = binding.statsGraph
chart.description.isEnabled = false
chart.setDrawGridBackground(false)
chart.setDrawBarShadow(false)
chart.isHighlightFullBarEnabled = false
chart.setBackgroundColor(Color.WHITE)
chart.setDrawGridBackground(false)
chart.setDrawBarShadow(false)
chart.setHighlightFullBarEnabled(false)
// draw bars behind lines
chart.setDrawOrder(
arrayOf(
CombinedChart.DrawOrder.BAR,
CombinedChart.DrawOrder.BUBBLE,
CombinedChart.DrawOrder.CANDLE,
CombinedChart.DrawOrder.LINE,
CombinedChart.DrawOrder.SCATTER
)
)
val legend = chart.getLegend()
legend.isWordWrapEnabled = true
legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM
legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER
legend.orientation = Legend.LegendOrientation.HORIZONTAL
legend.setDrawInside(false)
val rightAxis = chart.getAxisRight()
rightAxis.setDrawGridLines(false)
rightAxis.axisMinimum = 0f // this replaces setStartAtZero(true)
val leftAxis = chart.getAxisLeft()
leftAxis.setDrawGridLines(false)
leftAxis.axisMinimum = 0f // this replaces setStartAtZero(true)
val xAxis = chart.getXAxis()
xAxis.position = XAxis.XAxisPosition.BOTH_SIDED
xAxis.axisMinimum = 0f
xAxis.granularity = 1f
class MyValueFormatter : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
return value.toInt().toString()
}
}
xAxis.valueFormatter = MyValueFormatter()
val data = CombinedData()
data.setData(test())
xAxis.axisMaximum = data.xMax + 0.25f
chart.setData(data)
chart.invalidate()
You have to make sure that your layout and its parent layout has a "match_parent" width.

MPAndroid Chart not displaying any labels , what is missing?

I'm implementing a feature for displaying Target & Actual for properties .
So, I have to display Target labels according to filter selected for example if 3 Month filter selected then need to display March , Feb & Jan but what currently labels are not displaying on XAxis.
Here is my code , please rectify any issue:
fun showOrderChart(){
try {
orderChart.description.isEnabled=false
orderChart.setMaxVisibleValueCount(60)
// scaling can now only be done on x- and y-axis separately
// scaling can now only be done on x- and y-axis separately
orderChart.setPinchZoom(true)
orderChart.setDrawBarShadow(false)
orderChart.setDrawGridBackground(false)
/* val xAxis: XAxis = orderChart.xAxis
xAxis.position = XAxisPosition.BOTTOM
xAxis.setDrawGridLines(false)*/
orderChart.axisLeft.setDrawGridLines(false)
// add a nice and smooth animation
// add a nice and smooth animation
orderChart.animateY(1500)
orderChart.legend.isEnabled = false
val xVals = ArrayList<String>()
xVals.add("Jan")
xVals.add("Feb")
xVals.add("Mar")
xVals.add("Apr")
xVals.add("May")
xVals.add("Jun")
val yVals1 = ArrayList<BarEntry>()
val yVals2 = ArrayList<BarEntry>()
yVals1.add(BarEntry(1f, 1.toFloat()))
yVals2.add(BarEntry(1f, 2.toFloat()))
yVals1.add(BarEntry(2f, 3.toFloat()))
yVals2.add(BarEntry(2f, 4.toFloat()))
yVals1.add(BarEntry(3f, 5.toFloat()))
yVals2.add(BarEntry(3f, 6.toFloat()))
yVals1.add(BarEntry(4f, 7.toFloat()))
yVals2.add(BarEntry(4f, 5.toFloat()))
yVals1.add(BarEntry(5f, 9.toFloat()))
yVals2.add(BarEntry(5f, 12.toFloat()))
yVals1.add(BarEntry(6f, 11.toFloat()))
yVals2.add(BarEntry(6f, 8.toFloat()))
val set1:BarDataSet
val set2:BarDataSet
set1 = BarDataSet(yVals1, "Target")
set1.color = Color.RED
set2 = BarDataSet(yVals2, "Actual")
set2.color = Color.BLUE
val data = BarData(set1, set2)
data.setValueFormatter(LargeValueFormatter())
orderChart.data = data
orderChart.getBarData().setBarWidth(0.3f)
orderChart.xAxis.setAxisMinimum(0f)
orderChart.getXAxis().setAxisMaximum(0 + orderChart.getBarData().getGroupWidth(0.4f, 0f) * 6)
orderChart.groupBars(0f, 0.4f, 0f)
orderChart.getData().setHighlightEnabled(false)
orderChart.invalidate()
val l = orderChart.getLegend()
l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP)
l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT)
l.setOrientation(Legend.LegendOrientation.VERTICAL)
l.setDrawInside(true)
l.setYOffset(20f)
l.setXOffset(0f)
l.setYEntrySpace(0f)
l.setTextSize(8f)
val xAxis = orderChart.getXAxis()
xAxis.granularity = 1f
xAxis.setGranularityEnabled(true)
xAxis.setCenterAxisLabels(true)
xAxis.setDrawGridLines(false)
xAxis.setAxisMaximum(6f)
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM)
xAxis.setValueFormatter(IndexAxisValueFormatter(xVals))
orderChart.getAxisRight().setEnabled(false)
val leftAxis = orderChart.getAxisLeft()
leftAxis.setValueFormatter(LargeValueFormatter())
leftAxis.setDrawGridLines(true)
leftAxis.setSpaceTop(35f)
leftAxis.setAxisMinimum(0f)
}catch (e: Exception){
e.printStackTrace()
}
}
you need code for label. like this.
YAxis yAxisRight = lineChart.getAxisRight(); //set right of Y
yAxisRight.setDrawLabels(true);

Android MPChart | Align XAxis Labels with bars

I'm having a problem with aligning xAxis labels with actual bars.
I'm using MPChart for Android.
Here's an image of how it looks like:
As you can see, xAxis label is out of place. There should be one value under each group of bars.
I tried to fix it with
My code in Kotlin:
fun populateGraphData() {
var barChartView = findViewById<BarChart>(R.id.chartConsumptionGraph)
val barWidth: Float
val barSpace: Float
val groupSpace: Float
barWidth = 0.45f
barSpace = 0.1f
groupSpace = 0.56f
var titleobject = AvsF_response_year()
var xAxisValues = ArrayList<String>()
var yValueGroup1 = ArrayList<BarEntry>()
var yValueGroup2 = ArrayList<BarEntry>()
var barDataSet1: BarDataSet
var barDataSet2: BarDataSet
var i=1
for(value in avsfDateResponseList){
xAxisValues.add(value.dateTimeUTC)
yValueGroup1.add(BarEntry(i.toFloat(),value.dayAheadTotalLoadForecastValue.toFloat()))
yValueGroup2.add(BarEntry(i.toFloat(),value.actualTotalLoadValue.toFloat()))
i=i+1
}
barDataSet1 = BarDataSet(yValueGroup1, "")
barDataSet1.setColors(Color.CYAN, Color.CYAN)
barDataSet1.label = "DAY AHEAD TOTAL LOAD FORECAST"
barDataSet1.setDrawIcons(false)
barDataSet1.setDrawValues(false)
barDataSet2 = BarDataSet(yValueGroup2, "")
barDataSet2.label = "ACTUAL TOTAL LOAD"
barDataSet2.setColors(Color.BLUE, Color.BLUE)
barDataSet2.setDrawIcons(false)
barDataSet2.setDrawValues(false)
var barData = BarData(barDataSet1, barDataSet2)
barChartView.description.text = "entso-e"
barChartView.description.isEnabled = true
barChartView.description.textSize = 3f
barData.setValueFormatter(LargeValueFormatter())
barChartView.setData(barData)
barChartView.getBarData().setBarWidth(barWidth)
barChartView.getXAxis().setAxisMinimum(0f)
val size = avsfDateResponseList.size.toFloat() +avsfDateResponseList.size.toFloat()
barChartView.getXAxis().setAxisMaximum(size)
barChartView.groupBars(0f, groupSpace, barSpace)
barChartView.setFitBars(true)
barChartView.getData().setHighlightEnabled(true)
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("DAY AHEAD TOTAL LOAD FORECAST", Legend.LegendForm.SQUARE, 8f, 8f, null, Color.CYAN))
legenedEntries.add(LegendEntry("ACTUAL TOTAL LOAD", Legend.LegendForm.SQUARE, 8f, 8f, null, Color.BLUE))
legend.setCustom(legenedEntries)
legend.setYOffset(2f)
legend.setXOffset(2f)
legend.setYEntrySpace(0f)
legend.setTextSize(9f)
val xAxis = barChartView.getXAxis()
xAxis.setGranularity(1f)
xAxis.setGranularityEnabled(true)
xAxis.setCenterAxisLabels(true)
xAxis.setDrawGridLines(false)
xAxis.labelRotationAngle = 60F
xAxis.textSize = 10f
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM)
xAxis.setValueFormatter(IndexAxisValueFormatter(xAxisValues))
xAxis.setCenterAxisLabels(true)
xAxis.setLabelCount(avsfDateResponseList.size.toInt())
xAxis.setCenterAxisLabels(true)
xAxis.setAvoidFirstLastClipping(true)
barChartView.setDragEnabled(true)
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, 18f)
}
I've tried deleting and adding each one of these lines and nothing seems to be working right.
Can someone help me?

MPChart values overriding in Android

I have a MPChart and I am setting the values like this
lineChart.legend.isEnabled = false
lineChart.description.isEnabled = false
val entryList = arrayListOf<Entry>()
val sortedList = stockGraphResponse?.prices?.sortedWith(compareBy {
it?.date
})
for (i in 0 until sortedList?.size!!) {
val item = Utils.replaceCommaInNumber(sortedList[i]?.price!!).toFloat()
entryList.add(Entry(sortedList[i]?.date?.toFloat()!!, item))
}
val lineDataSet = LineDataSet(entryList,"")
lineDataSet.setDrawCircles(false)
lineDataSet.setDrawFilled(true)
val lineData = LineData(lineDataSet)
lineChart.data = lineData
lineChart.setDrawBorders(true)
val xAxis = lineChart.xAxis
xAxis.position = XAxis.XAxisPosition.BOTTOM
xAxis.setValueFormatter(CustomFormatter())
xAxis.setLabelCount(5,true)
val yAxis = lineChart.axisLeft
val yRight = lineChart.axisRight
yRight.isEnabled = false
lineChart.isAutoScaleMinMaxEnabled = true
lineChart.invalidate()
And the result is this graph
I am setting 5 for label count in xAxis and I am getting 5 labels but then the values are being plotted like that and so they are overlapping. I tried using granularity but still the same. How can I streamline this? Any help would be appreciated. Thanks

Categories

Resources