Search code examples
iosswiftios-charts

Barchart with grouped values: center-align x-axis labels


I'm using the Charts library to generate a bar chart. This is the design I've been given, which I am trying to recreate:

enter image description here

This is what I've managed to build:

enter image description here

It's getting close, but I'm having serious issues showing the bars. For example, the x-axis labels need to be shown in the center of the group, not directly under the vertical line. And the last gray bar is not shown at all for some reason.

Code:

import Charts
import UIKit

class DayAxisValueFormatter: NSObject, IAxisValueFormatter {
  public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
    let day = Int(value)
    return ["Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu"][day]
  }
}

class ReportBarChart: UITableViewCell {
  @IBOutlet private var chartView: BarChartView!

  let groupSpace = 0.06
  let barSpace = 0.02
  let barWidth = 0.45

  override func awakeFromNib() {
    super.awakeFromNib()

    chartView.backgroundColor = .reportCard
    chartView.drawBarShadowEnabled = false
    chartView.drawValueAboveBarEnabled = false
    chartView.dragEnabled = false
    chartView.setScaleEnabled(false)
    chartView.pinchZoomEnabled = false

    let xAxis = chartView.xAxis
    xAxis.labelPosition = .bottom
    xAxis.labelFont = .systemFont(ofSize: 11, weight: .semibold)
    xAxis.labelTextColor = .reportGrayText
    xAxis.granularity = 1
    xAxis.labelCount = 7
    xAxis.valueFormatter = DayAxisValueFormatter()

    let leftAxis = chartView.leftAxis
    leftAxis.enabled = false

    let rightAxis = chartView.rightAxis
    rightAxis.enabled = true
    rightAxis.labelFont = .systemFont(ofSize: 11, weight: .semibold)
    rightAxis.labelTextColor = .reportGrayText
    rightAxis.axisMinimum = 0
    rightAxis.labelCount = 3

    let legend = chartView.legend
    legend.font = .systemFont(ofSize: 11, weight: .semibold)
    legend.textColor = .white
    legend.form = .circle
    legend.xEntrySpace = 16
  }

  func configure() {
    let currentValues = [
      BarChartDataEntry(x: 0, y: 1),
      BarChartDataEntry(x: 1, y: 2),
      BarChartDataEntry(x: 2, y: 3),
      BarChartDataEntry(x: 3, y: 4),
      BarChartDataEntry(x: 4, y: 4),
      BarChartDataEntry(x: 5, y: 1),
      BarChartDataEntry(x: 6, y: 6),
    ]

    let currentValuesSet = BarChartDataSet(entries: currentValues, label: "This week")
    currentValuesSet.setColor(UIColor.reportOrange)
    currentValuesSet.drawValuesEnabled = false

    let previousValues = [
      BarChartDataEntry(x: 0, y: 4),
      BarChartDataEntry(x: 1, y: 3),
      BarChartDataEntry(x: 2, y: 2),
      BarChartDataEntry(x: 3, y: 1),
      BarChartDataEntry(x: 4, y: 3),
      BarChartDataEntry(x: 5, y: 2),
      BarChartDataEntry(x: 6, y: 5),
    ]

    let previousValuesSet = BarChartDataSet(entries: previousValues, label: "Last week")
    previousValuesSet.setColor(UIColor.reportGrayChart)
    previousValuesSet.drawValuesEnabled = false

    let data = BarChartData(dataSets: [currentValuesSet, previousValuesSet])
    data.highlightEnabled = false

    data.barWidth = barWidth
    data.groupBars(fromX: 0, groupSpace: groupSpace, barSpace: barSpace)

    chartView.data = data
  }
}

Solution

  • Okay, found the answer 😅

    xAxis.axisMinimum = 0
    xAxis.axisMaximum = 7
    xAxis.centerAxisLabelsEnabled = true