[ad_1]
I am using the BarChartView from the iOS-Charts library. However, when I stack the bars, sometimes the labels for these bars overlap. Is there a way to prevent this from happening? Some ideas I had:
- Is it possible to position these labels on either side of the bars?
- Is it possible to only display a label if it is not 0?
- Is it possible to scale the bar size down if it is way larger (like the first bar in the image)?
Here is my code:
import UIKit
import Charts
struct BarChartInformation: Decodable {
public let title: String?
public let isStacked: Bool?
public let numberDataType: String?
public let data: [SingleBarChartInformation]?
private enum CodingKeys: String, CodingKey {
case title = "title"
case isStacked = "isStacked"
case numberDataType = "numberDataType"
case data = "data"
}
}
struct SingleBarChartInformation: Decodable {
public let title: String?
public let values: [Double]?
public let labels: [String]?
public let color: String?
private enum CodingKeys: String, CodingKey {
case title = "title"
case values = "values"
case labels = "labels"
case color = "color"
}
}
class BarChartTableViewCell: BorderCardTableViewCell {
let barChart = BarChartView(frame: .zero)
let titleLabel = UILabel(frame: .zero)
var cellData: BarChartInformation? {
didSet {
guard let cellData = cellData else { return }
let data = ChartHelpers().makeCustomBarChart(chartData: cellData)
var axisSize = Double((cellData.data?.get(index: 0)?.values?.count ?? 0)) - 0.5
let labels = cellData.data?.get(index: 0)?.labels
var finalLabels = [String]()
for label in labels ?? [String]() {
if cellData.isStacked == false {
for _ in 0...(cellData.data?.count ?? 2)-2 {
finalLabels.append("")
}
}
finalLabels.append(label)
}
if cellData.isStacked == false {
axisSize *= Double(cellData.data?.count ?? 1)
barChart.xAxis.axisMinimum = 0
}
barChart.xAxis.axisMaximum = axisSize
barChart.xAxis.axisMaxLabels = Int(axisSize)
barChart.xAxis.valueFormatter = IndexAxisValueFormatter(values: finalLabels)
barChart.xAxis.granularityEnabled = true
barChart.xAxis.granularity = 1
barChart.data = data
barChart.xAxis.labelPosition = .bottom
titleLabel.text = cellData.title
self.contentView.layoutIfNeeded()
}
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addTimelineChart()
addLabels()
self.contentView.layoutIfNeeded()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func addTimelineChart() {
borderView.addSubview(barChart)
barChart.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
barChart.topAnchor.constraint(equalTo: self.borderView.topAnchor, constant: 58),
barChart.bottomAnchor.constraint(equalTo: self.borderView.bottomAnchor),
barChart.rightAnchor.constraint(equalTo: self.borderView.rightAnchor),
barChart.leftAnchor.constraint(equalTo: self.borderView.leftAnchor),
])
barChart.animate(xAxisDuration: 0.5, yAxisDuration: 0.5)
barChart.xAxis.labelTextColor = .label
barChart.xAxis.labelPosition = .bottom
barChart.xAxis.drawLabelsEnabled = true
barChart.xAxis.drawGridLinesEnabled = false
barChart.chartDescription?.enabled = true
barChart.xAxis.enabled = true
barChart.legend.enabled = true
barChart.rightAxis.enabled = false
barChart.leftAxis.enabled = false
barChart.leftAxis.drawGridLinesEnabled = false
barChart.rightAxis.drawGridLinesEnabled = false
barChart.xAxis.drawGridLinesEnabled = false
barChart.doubleTapToZoomEnabled = false
barChart.backgroundColor = .clear
barChart.dragEnabled = false
barChart.highlightFullBarEnabled = false
barChart.contentMode = .scaleAspectFit
}
func addLabels() {
titleLabel.font = Constants.Fonts.bold3
titleLabel.textColor = .label
titleLabel.textAlignment = .left
borderView.addSubview(titleLabel)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
titleLabel.topAnchor.constraint(equalTo: borderView.topAnchor, constant: 4),
titleLabel.leftAnchor.constraint(equalTo: borderView.leftAnchor, constant: 12),
titleLabel.heightAnchor.constraint(equalToConstant: 26),
])
let line = UIView(frame: .zero)
line.backgroundColor = Constants.borderColor
borderView.addSubview(line)
line.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
line.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 2),
line.rightAnchor.constraint(equalTo: borderView.rightAnchor, constant: -Constants.borderWidth),
line.leftAnchor.constraint(equalTo: borderView.leftAnchor, constant: Constants.borderWidth),
line.heightAnchor.constraint(equalToConstant: Constants.borderWidth),
])
}
}
func makeCustomBarChart(chartData: BarChartInformation) -> BarChartData {
var dataSets: [BarChartDataSet] = []
let stacked: Bool = chartData.isStacked ?? true
for i in 0..<(chartData.data?.count ?? 0) {
var entries: [BarChartDataEntry] = []
for ii in 0..<(chartData.data?.get(index: i)?.values?.count ?? 0) {
guard let data = chartData.data, let values = data.get(index: i)?.values else {
return BarChartData(dataSets: [])
}
let dataEntry = BarChartDataEntry(x: Double(ii), y: values.get(index: ii) ?? 0)
entries.append(dataEntry)
}
let dataSet = BarChartDataSet(entries: entries, label: chartData.data?.get(index: i)?.title)
if let color = chartData.data?.get(index: i)?.color {
dataSet.setColor(UIColor(hexString: color))
} else {
dataSet.setColor(UIColor(hexString: "#FFFFFF"))
}
dataSets.append(dataSet)
}
let data = BarChartData(dataSets: dataSets)
if !stacked {
data.groupBars(fromX: 0, groupSpace: 0, barSpace: 0)
} else {
}
let formatter = NumberFormatter()
formatter.numberStyle = String.asNumberStyle(string: chartData.numberDataType)
formatter.maximumFractionDigits = 0
formatter.multiplier = 1.0
data.setValueFormatter(DefaultValueFormatter(formatter:formatter))
return data
}
[ad_2]