Search code examples
ios-charts

Custom xAxis formatting in iOS Charts library


I'm using the following library to implement charts in my iOS app: https://github.com/danielgindi/Charts

On the xAxis I would like to have a formatting similar to the one on the screenshot. I would like to display the name of the month once, followed by days of that month (without month name), and when the months changes, display the name again.

Can someone point to the right direction? enter image description here

Current code for xAxis configuration, which shows month and day for each entry:

xAxis.drawAxisLineEnabled = true
xAxis.drawGridLinesEnabled = false
xAxis.centerAxisLabelsEnabled = true
xAxis.drawLabelsEnabled = true
xAxis.axisLineColor = R.Color.Chart.Alpha.separator
xAxis.labelTextColor = R.Color.Chart.Alpha.content
xAxis.labelPosition = .bottom
xAxis.labelCount = 5
xAxis.valueFormatter = XAxisValueFormatter()

class XAxisValueFormatter: AxisValueFormatter {

    func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        let date = Date(timeIntervalSince1970: value)
        return date.to(DateFormat.monthday)
    }
}

Solution

  • You need to update your existing code as below.

    1. Update your data binding for XAxis:
    let chartFormatter = LineChartFormatter(labels: xValues)
    let xAxis = XAxis()
    xAxis.valueFormatter = chartFormatter
    self.xAxis.valueFormatter = xAxis.valueFormatter
    
    1. Update Value Formatter code:

      private class LineChartFormatter: NSObject, IAxisValueFormatter {
      
      var labels: [String] = []
      let dateFormatter = DateFormatter()
      let dateShortFormatter = DateFormatter()
      
      func stringForValue(_ value: Double, axis: AxisBase?) -> String {
      
      
          if let date = dateFormatter.date(from:labels[Int(value)]) {
              if value == 0 {
                  dateShortFormatter.dateFormat = "MMM dd"
                  return dateShortFormatter.string(from: date)
              } else {
      
                  let prevDate = dateFormatter.date(from:labels[Int(value - 1)])
                  dateShortFormatter.dateFormat = "MMM"
                  if dateShortFormatter.string(from: date) != dateShortFormatter.string(from: prevDate!) {
                      dateShortFormatter.dateFormat = "MMM dd"
                      return dateShortFormatter.string(from: date)
                  } else {
                      dateShortFormatter.dateFormat = "dd"
                      return dateShortFormatter.string(from: date)
                  }
              }
          } else {
            return labels[Int(value)]
          }
      }
      
      init(labels: [String]) {
          super.init()
          dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
          self.labels = labels
      }}
      

    By Above code change, you will achieve your Date formatting in XAxis.