Wrong values on x-axis on linechart - android

I'm using MPAndroidChart in my android application but the x-axis is wrong formatted and label are duplicated. Here my code
private fun lineChart(exams: List<Exam>) {
val formatter: DateFormat = SimpleDateFormat("dd/MM/yyyy")
val lineChart: LineChart = linechart
lineChart.animateY(1000)
val d = Description()
d.text = "TEST"
lineChart.description = d
val yValues: ArrayList<Entry> = ArrayList()
var count = 0
for (exam in exams.sortedByDescending { exam -> exam.date }) {
if (getString(R.string.scores_array_admitted) != exam.score)
yValues.add(Entry(count++.toFloat(), exam.score.toFloat()))
}
val lineDataSet = LineDataSet(yValues, getString(R.string.linechart_score_label))
val dataSet: ArrayList<ILineDataSet> = ArrayList()
dataSet.add(lineDataSet)
val lineData = LineData(dataSet)
val xAxis: XAxis = lineChart.xAxis
val values = ArrayList<String>()
for (exam in exams.sortedByDescending { exam -> exam.date }) {
if (getString(R.string.scores_array_admitted) != exam.score)
values.add(formatter.format(exam.date))
}
val array = arrayOfNulls<String>(values.size)
values.toArray(array)
var aa = array!!
xAxis.valueFormatter = MyAxisValueFormatter(aa)
lineChart.data = lineData
}
In debug I see that the value in the arrays are correct, 2 exams and in values array the label are the two date of the exam and they are exactly two, but when I run my application the result is this
In x axis I would have only two date

Related

how to show min and max value in linechart using mpchart in Android

I want to show the Min and Max value on the line chart i am using the library MPChart Android library.
I want to show min max as like this.
My Code for the Line chart
val lineDataSet = LineDataSet(values, "")
lineDataSet.lineWidth = 2f
lineDataSet.setDrawValues(true)
lineDataSet.setDrawFilled(true)
// lineDataSet.fillAlpha = 85
lineDataSet.setDrawCircles(false)
// lineDataSet.setCircleColor(Color.BLACK)
lineDataSet.color = resources.getColor(R.color.green)
// lineDataSet.fillColor = resources.getColor(R.color.colorPrimary)
lineDataSet.highLightColor = resources.getColor(R.color.coral);
val elevationMarker = ChartMarkerView2(activity)
binding!!.chart.markerView = elevationMarker
lineDataSet.setDrawHighlightIndicators(true)
lineDataSet.setDrawHorizontalHighlightIndicator(false)
lineDataSet.setDrawCircleHole(true)
lineDataSet.circleHoleRadius = 5f
lineDataSet.setCircleColor(
resources.getColor(R.color.green)
)
val drawable = ContextCompat.getDrawable(requireContext(), R.drawable.fade_graph_bg)
lineDataSet.fillDrawable = drawable
lineDataSet.axisDependency = YAxis.AxisDependency.LEFT
// lineDataSet.cubicIntensity = 0f
// lineDataSet.mode = LineDataSet.Mode.HORIZONTAL_BEZIER;
val dataSets = ArrayList<ILineDataSet>()
dataSets.add(lineDataSet) // add the datasets
// create a data object with the datasets
val data = LineData(dataSets)
// data.setDrawValues(false)
// set data
binding!!.chart.data = data
// binding!!.chart.animateX(100)
binding!!.chart.invalidate()
you can get Max- Min your Dataset and in ValueFormatter Modify your value like this :
val numArr1 = intArrayOf(10000, 10100, 12200,12700, 9036, 11200, 10200)
val max = numArr1.maxOrNull() ?: 0
val min = numArr1.minOrNull() ?: 0
valueFormatter = object : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
if (value == min.toFloat() || value == max.toFloat())
{
return "$value $"
}
return ""
}
}
Here is the code snippet to set minimum and maximum value in Linechart using MPAndroidChart library.
val chartEntities: ArrayList<Entry> = ArrayList()
val values = Array(5) {0f}
values[0] = 5f
values[1] = 2.2f
values[2] = 7.2f
values[3] = 9.5f
values[4] = 4.5f
values[5] = 6.4f
var i = 0
for (entry in values) {
var value = values[i]
chartEntities.add(Entry(i.toFloat(), value))
i++
}
val lineDataSet = LineDataSet(chartEntities, "")
val max = values.maxOrNull() ?: 0
val min = values.minOrNull() ?: 0
val valueFormatter = object : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
if (value == min.toFloat() || value == max.toFloat())
{
return "$value"
}
return ""
}
}
lineDataSet.valueFormatter = valueFormatter
lineDataSet.setDrawValues(true)
With this sample snippet you can set minimum and maximum values in linechart using MPAndroidChart.
Create float array of items to display in the line chart
find out minimum and maximum values from the arraylist.
create ValueFormatter and set values there.
set valueFormatter property to lineDataSet
set setDrawValues(true) in lineDataSet
Hope this helps. Happy coding.

How to remove stronger line in the middle of graph for android MPAndroidChart

My MPAndroidChart displays a stronger line to represent the middle of the graph. How do I avoid that please?
Here is what I have at the moment:
private fun addChart(totals: Totals) {
chart1.apply {
isDragEnabled = true
isScaleXEnabled = false
isScaleYEnabled = true
axisRight.isEnabled = false
axisLeft.setDrawAxisLine(false)
xAxis.isEnabled = false
legend.isEnabled = false
description.text = ""
setTouchEnabled(false)
}
val y: YAxis = chart1.axisLeft
y.axisMaximum = 800f
y.axisMinimum = 0f
y.labelCount = 5
val yValues = ArrayList<Entry>()
for ((index, i) in totals.features!!.withIndex()) {
yValues.add(Entry(index.toFloat(), i.attributes?.confirmedCovidCases!!.toFloat()))
}
val set1 = LineDataSet(yValues, "Data set 1")
set1.color = resources.getColor(R.color.orange)
set1.setDrawCircles(false)
val dataSets = ArrayList<ILineDataSet>()
dataSets.add(set1)
val data = LineData(dataSets)
chart1.data = data
}
Thank you very much.
I try to recreate your chart but did not have the problem
Try to run it on device, because it might your PC/simulator pixel bleeding

MPAndroidChart - How to display a date only once on x axis with data points in milliseconds?

I have a LineChart in my app. The x value of the data points I use are milliseconds that I display as a date using ValueFormatter. This works fine, except I only want the date to be displayed once. I tried the following code, and it almost works, however it only works for the first date displayed. Any help appreciated!
Here is an example of my problem:
This is my most successful code, I use kotlin:
val xAxis = chart.xAxis
xAxis.position = XAxis.XAxisPosition.BOTTOM
val dateFormatter = SimpleDateFormat("dd/MM")
var lastDate = ""
val formatter = object : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
val date = dateFormatter.format(Date(value.toLong()))
if (date==lastDate){
return ""
}
lastDate = date
return date
}
}
xAxis.valueFormatter = formatter
The following is the whole function, the json is temporary and is only there for testing purposes, the app will receive similar jsons.
private fun chart(){
val json = JSONObject("""{"payload":{"serie":{"data":
[[1564129484189,3287],[1564129933626,3287],[1564130385185,3287],[1564130834622,3280],[1564131284854,3280],[1564131736401,3280],
[1564132184652,3280],[1564132634092,3280],[1564133083925,3280],[1564133534963,3287],[1564133984117,3287],[1564134434677,3287],
[1564134883854,3280],[1564135333830,3280],[1564135785080,3280],[1564136234991,3280],[1564136685793,3280],[1564137134667,3280],
[1564137584570,3280],[1564138034367,3280],[1564138484236,3280],[1564138934104,3273],[1564139384690,3273],[1564139834549,3273],
[1564140284417,3280],[1564140734298,3280],[1564141183544,3280],[1564141634006,3273],[1564142083871,3273],[1564142533644,3273],
[1564142984818,3273],[1564143433797,3273],[1564143883681,3273],[1564144334485,3273],[1564144785207,3273],[1564145234378,3273],
[1564145685180,3280],[1564146134070,3280],[1564146584966,3280],[1564147034886,3280],[1564147484703,3280],[1564147934612,3280],
[1564148384456,3280],[1564148834343,3280],[1564149283943,3280],[1564149734825,3280],[1564150184715,3280],[1564150634494,3280],
[1564151084377,3287],[1564151534299,3287],[1564151984188,3287],[1564215691264,3287],[1564216142234,3287],[1564216591762,3287],
[1564217041687,3287],[1564217491103,3287],[1564217941061,3287],[1564218391529,3287],[1564218841469,3287],[1564219291586,3287],
[1564219741426,3287],[1564220192557,3287],[1564220641356,3287],[1564221091465,3280],[1564221541440,3280],[1564221991829,3280],
[1564222441313,3287],[1564222893010,3287],[1564223344202,3287],[1564223792494,3280],[1564224696695,3280],[1564225144701,3280],
[1564225591575,3280],[1564226047071,3280],[1564226492027,3280],[1564226951626,3280],[1564227392573,3280],[1564227841277,3280],
[1564228292385,3287],[1564228741844,3287],[1564229192885,3287],[1564229642831,3287],[1564230092311,3287],[1564230550690,3287],
[1564230993205,3287],[1564231443101,3287],[1564231892541,3287],[1564232344078,3280],[1564232793143,3280],[1564233255081,3280]]}}}""")
val payload = json.get("payload") as JSONObject
val serie = payload.get("serie") as JSONObject
val dataPoints = serie.get("data") as JSONArray
val values = arrayListOf<Entry>()
for (i in 0 until dataPoints.length()) {
val innerData = dataPoints[i] as JSONArray
values.add (Entry(
innerData[0].toString().toFloat() ,
innerData[1].toString().toFloat()
))
}
val chart = findViewById<LineChart>(R.id.graph2)
chart.setTouchEnabled(true)
chart.setPinchZoom(true)
chart.isScaleYEnabled = false
val dataSet = LineDataSet(values, "Service")
dataSet.color = ContextCompat.getColor(this, R.color.colorAccent)
dataSet.setCircleColor(ContextCompat.getColor(this, R.color.colorPrimaryDark))
dataSet.setDrawValues(false)
dataSet.lineWidth = 2f
val xAxis = chart.xAxis
xAxis.position = XAxis.XAxisPosition.BOTTOM
val dateFormatter = SimpleDateFormat("dd/MM")
var lastDate = ""
val formatter = object : ValueFormatter() {
override fun getFormattedValue(value: Float): String {
val date = dateFormatter.format(Date(value.toLong()))
if (date==lastDate){
return ""
}
lastDate = date
return date
}
}
xAxis.valueFormatter = formatter
val yAxisRight = chart.axisRight
yAxisRight.isEnabled = false
val yAxisLeft = chart.axisLeft
yAxisLeft.granularity = 1f
val desc = Description()
desc.text = "custom description"
chart.description = desc
val data = LineData(dataSet)
chart.data = data
chart.animateX(1000)
chart.invalidate()
}
I don't know in kotlin but in java or for some idea you can refer to my answer in the given link- DateTime axis in MPAndroidChart
I'm attaching the code in which I've used IndexAxisValueFormatter. Also declare dev String array in your class final String dev[] = new String[100]; and use it as in below code.
for (int i = 0; i < jsonArray1.length(); i++) {
JSONObject object1 = jsonArray1.getJSONObject(i);
dev[i] = object1.getString("block_time"); //for xaxis needed
XAxis bottomAxis = lineChart.getXAxis();
bottomAxis.setValueFormatter(new IndexAxisValueFormatter(dev));/*for x axis values*/
bottomAxis.setLabelCount(lineEntries.size());
bottomAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
bottomAxis.setDrawLabels(true); //to hide all xaxis values
bottomAxis.setDrawGridLines(false);
bottomAxis.setDrawAxisLine(true);}

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

Graph using mpAndroid Chart xAxis is not displaying the date i formatted

I have a code to display a data in a line graph and I need to change the xAxis to date but the log have a error
java.lang.NumberFormatException: For input string: "2019-04-19 00:00:00"
Below is my code snippet for line graph
mLineChart = findViewById(R.id.chart)
importData()
val dataSet = LineDataSet(entries, "Water")
val lineData = LineData(dataSet)
mLineChart.axisRight.isEnabled = false
mLineChart.data = lineData
dataSet.color = Color.RED
dataSet.setDrawCircles(false)
dataSet.setDrawValues(false)
dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER
mLineChart.description.text = ""
mLineChart.legend.isEnabled = false
mLineChart.invalidate()
val leftAxis = mLineChart.axisLeft
leftAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART)
leftAxis.axisMinimum = 0f
leftAxis.axisMaximum = 30f
val rightAxis = mLineChart.axisRight
rightAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART)
rightAxis.axisMinimum = 0f
rightAxis.axisMaximum = 30f
var xAxis = mLineChart.xAxis
xAxis.position = XAxis.XAxisPosition.BOTTOM
xAxis.setDrawGridLines(false)
xAxis.axisMinimum = 0f
xAxis.labelCount = 5
xAxis.axisMaximum = 400f
xAxis.granularity = 1f
xAxis.isGranularityEnabled = true
xAxis.valueFormatter = DateAxisValueFormatter(null)
Below is my code snippet for inserting data
private fun importData() {
for (data in dataList) {
val date = java.lang.Float.parseFloat(data.date)
val water = java.lang.Float.parseFloat(data.water)
entries.add(Entry(date, water))
}
Below is my code snippet for value formatter
internal inner class DateAxisValueFormatter(private val mValues: Array<String>?) : ValueFormatter(),
IAxisValueFormatter {
var sdf = SimpleDateFormat("hh:mm", Locale.ENGLISH)
override fun getFormattedValue(value: Float, axis: AxisBase?): String {
return sdf.format(Date(value.toLong()))
}
}
Your exception is clear, you're trying to convert a string into Float, but this string is not a Number.
If you want to display a date, you have to format your date in milliseconds before.
Try something like that:
private fun importData() {
val dateFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH)
for (data in dataList) {
val date = dateFormatter.parse(data.date)
val water = java.lang.Float.parseFloat(data.water)
//Here you get your date as a Long and you convert it in Float
entries.add(Entry(date.time.toFloat(), water))
}
EDIT:
In your xAxis set your own valueFormatter this way to convert your float back in date:
val x = chart.xAxis
x.setValueFormatter { value, _ ->
SimpleDateFormat("HH:mm:ss", Locale.ENGLISH).format(value.toLong())
}

Categories

Resources