Computersmith64
Computersmith64

Reputation: 53

MPAndroidChart - make xaxis spacing relative

I have an MPAndroidChart line chart that shows dates on the xaxis & weights on the yaxis. As it is, the data points along the xaxis are all evenly spaced, but I'd like to make them relative to the time period between each weight entry. Try as I might, I can't find anything in the MPAndroidChart documentation that describes how to do this, or if it's even supported. Can anyone point me in the right direction here?

Here is the code to create the chart (with the result being even spacing):

private fun loadChart(weightList: List<FormattedWeight>) {
    if (weightList.isEmpty()) { return }
        
    val weights = ArrayList<Entry>()
    val dates = ArrayList<Date>()


    for (i in weightList.indices) {
        val weight = weightList[i]
        weights.add(Entry(i.toFloat(), weight.Weight!!.toFloat()))
        dates.add(weight.WeightDate!!)
    }
    val dataSet = LineDataSet(weights, "Weights")
    dataSet.mode = LineDataSet.Mode.LINEAR

    val xaxis = binding.weightChart.xAxis

    xaxis.granularity=2f
    dataSet.color = Color.BLUE
    dataSet.setCircleColor(Color.BLUE)
    xaxis.position = XAxis.XAxisPosition.BOTTOM

    xaxis.valueFormatter = object : ValueFormatter() {
        private val mFormat = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT)
        override fun getFormattedValue(value: Float): String {
            return try {
                mFormat.format(dates[value.toInt()])
            } catch (e: Exception) {
                ""
            }
        }
    }

    binding.weightChart.data = LineData(dataSet)
    binding.weightChart.description.isEnabled = false
    binding.weightChart.legend.isEnabled = false
    binding.weightChart.invalidate()
    binding.weightChart.moveViewToX(weights[weights.size - 1].y)

}

Even spacing Line Chart (even spacing)

Relative spacing Line Chart (relative spacing)

Upvotes: 1

Views: 131

Answers (1)

Computersmith64
Computersmith64

Reputation: 53

I figured out that the xaxis spacing is set in

Entry(float x, float y)

If you set the x parameter to evenly incremented numbers (eg: 1, 2, 3...) you will get evenly spaced data points. However if you set them to varying increments (eg: 1, 1.3, 2.2...), you'll get relative spacing. So here's the code I used to achieve this:

    val spacing = calcRelativeSpacing(weightList)
    
    for (i in weightList.indices) {
        val weight = weightList[i]
        weights.add(Entry(spacing[i], weight.Weight!!.toFloat()))
        dates.add(weight.WeightDate!!)
    }

Note the call to calcRelativeSpacing(weightList):

private fun calcRelativeSpacing(entries: List<FormattedWeight>): ArrayList<Float> {
    val startDate = Instant(entries.get(0).WeightDate)
    val endDate = Instant(entries.get(entries.lastIndex).WeightDate)
    val days = Days.daysBetween(startDate, endDate).days
    val dayInterval = (days / entries.size).toFloat()
    val spacing = ArrayList<Float>()
    spacing.add(1f)
    for (i in 1 until entries.size) {
        spacing.add(spacing[i-1] + (Days.daysBetween(Instant(entries.get(i-1).WeightDate), Instant(entries.get(i).WeightDate)).days / dayInterval))
    }
    return spacing
}

The result: enter image description here

Upvotes: 0

Related Questions