XAxis labels not shown despite stringForValue getting called - swift

I have a LineChartView and I want to show labels for the xAxis.
My code looks like this:
chartView.chartDescription?.enabled = false
chartView.drawGridBackgroundEnabled = false
chartView.dragEnabled = !chartView.isFullyZoomedOut
chartView.setScaleEnabled(true)
chartView.pinchZoomEnabled = true
chartView.setViewPortOffsets(left: 20.0, top: 0.0, right: 20.0, bottom: 0.0)
chartView.legend.enabled = true
chartView.legend.textColor = legendColor
chartView.legend.form = .empty
chartView.leftAxis.enabled = false
chartView.leftAxis.spaceTop = 0.4
chartView.leftAxis.spaceBottom = 0.4
chartView.rightAxis.enabled = false
chartView.xAxis.enabled = true
chartView.xAxis.labelTextColor = UIColor.black
chartView.xAxis.valueFormatter = self
chartView.xAxis.drawGridLinesEnabled = false
chartView.xAxis.drawLabelsEnabled = true
chartView.xAxis.drawAxisLineEnabled = false
chartView.highlightPerTapEnabled = false
chartView.highlightPerDragEnabled = false
if lineChartData.entryCount > 0 {
chartView.data = lineChartData
}
chartView.noDataText = NSLocalizedString("No chart data available", comment: String())
chartView.maxVisibleCount = 12
chartView.delegate = self
and
extension ChartCell: IAxisValueFormatter {
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
return "foo"
}
}
In the debugger I see that stringForValue is being called, however in the drawn charts there are no labels.
I'm at a loss what I am missing here.

You have to set below :
chartView.xAxis.labelPosition = XAxis.LabelPosition.bottom

Related

Create horizontal bar chart with scpecific data

I'm learning how to create charts and I'm at the point where I need to use more complex data. I created charts where the usual ranges were used.
This is what my chart looks like now
What I need to end up with.
I don't know how to change the axes data according to the array:
items = [AgeItem(ageGroup: ">60", iqLevel: 95),
AgeItem(ageGroup: "45-60", iqLevel: 118),
AgeItem(ageGroup: "35-44", iqLevel: 141),
AgeItem(ageGroup: "25-34", iqLevel: 106),
AgeItem(ageGroup: "18-24", iqLevel: 126),
AgeItem(ageGroup: "16-17", iqLevel: 100)]
The task is to create a graph that will display how many points a person from a certain age group scored when passing the test. Y-axis - age group, X-axis - test points. I also need to add a "you" chart bar that will stand out from the others.
Here is my graph code:
override func awakeFromNib() {
super.awakeFromNib()
self.setup(barLineChartView: chartView)
chartView.delegate = self
chartView.drawBarShadowEnabled = false
chartView.drawValueAboveBarEnabled = true
chartView.maxVisibleCount = 60
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.labelFont = .systemFont(ofSize: 10)
xAxis.drawAxisLineEnabled = true
xAxis.granularity = 10
xAxis.labelTextColor = .white
let leftAxis = chartView.leftAxis
leftAxis.labelFont = .systemFont(ofSize: 10)
leftAxis.drawAxisLineEnabled = true
leftAxis.drawGridLinesEnabled = true
leftAxis.axisMinimum = 0
leftAxis.labelTextColor = .white
let rightAxis = chartView.rightAxis
rightAxis.enabled = true
rightAxis.labelFont = .systemFont(ofSize: 10)
rightAxis.drawAxisLineEnabled = true
rightAxis.axisMinimum = 0
rightAxis.labelTextColor = .white
chartView.fitBars = true
chartView.animate(yAxisDuration: 2.5)
self.setDataCount(Int(12) + 1, range: UInt32(190))
}
func setDataCount(_ count: Int, range: UInt32) {
let barWidth = 9.0
let spaceForBar = 10.0
let yVals = (0..<count).map { (i) -> BarChartDataEntry in
let mult = range + 1
let val = Double(arc4random_uniform(mult))
return BarChartDataEntry(x: Double(i)*spaceForBar, y: val)
}
let set1 = BarChartDataSet(entries: yVals)
set1.drawIconsEnabled = false
let data = BarChartData(dataSet: set1)
data.setValueFont(UIFont.poppins(size: 12))
data.barWidth = barWidth
data.setValueTextColor(.white)
chartView.data = data
}
func setup(barLineChartView chartView: BarLineChartViewBase) {
chartView.chartDescription.enabled = false
chartView.dragEnabled = true
chartView.setScaleEnabled(true)
chartView.pinchZoomEnabled = false
// ChartYAxis *leftAxis = chartView.leftAxis;
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
chartView.rightAxis.enabled = false
}

Line chart lines with same value are overlapping

I am using danielgindi
/
Charts for creating line chart. When Line chart data has same values, only the last drawn line showing. Other lines are hidden behind the last drawn line. Is there any way to show all lines.
image: 'fff' and 'User B' is hidden behind 'User C', they all have number of activities equal to zero
Line chart initialisation
func commonInit() {
guard let view = loadViewFromNib() else { return }
view.frame = self.bounds
self.addSubview(view)
lblXAxis.text = "Days"
lblYAxis.text = "Number of Activities"
lblYAxis.transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
self.roundAllCorners(radius: 6)
let valFormatter = NumberFormatter()
valFormatter.numberStyle = .none
valFormatter.maximumFractionDigits = 0
viewProgressLineChart.leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: valFormatter)
viewProgressLineChart.leftAxis.granularity = 1
viewProgressLineChart.xAxis.granularity = 1
viewProgressLineChart.xAxis.labelCount = 11
viewProgressLineChart.xAxis.avoidFirstLastClippingEnabled = false
viewProgressLineChart.xAxis.labelPosition = .bottom
viewProgressLineChart.chartDescription?.text = ""
viewProgressLineChart.xAxis.labelTextColor = UIColor.onPrimary
viewProgressLineChart.leftAxis.labelTextColor = UIColor.onPrimary
viewProgressLineChart.rightAxis.labelTextColor = UIColor.onPrimary
viewProgressLineChart.clipValuesToContentEnabled = true
viewProgressLineChart.legend.enabled = false
viewProgressLineChart.rightAxis.enabled = false
viewProgressLineChart.animate(xAxisDuration: 0.8)
}
This is how data is given to line chart,
func updateGraph(users: [User]){
let data = LineChartData()
for (index,user) in users.enumerated(){
let userColor = UIColor.selectedColors[index]
userAndStatusColorArray.append(UserAndStatusColor(name: user.name ?? "user", color: userColor))
var lineChartEntry = [ChartDataEntry]()
if user.progress != nil{
for progress in user.progress!{
let chartData = ChartDataEntry(x: Double(progress.day), y: Double(progress.activitiesCompleted!))
lineChartEntry.append(chartData)
}
let chartDataSet = LineChartDataSet(entries: lineChartEntry)
chartDataSet.colors = [userColor]
chartDataSet.circleColors = [userColor]
chartDataSet.circleRadius = 3
chartDataSet.drawValuesEnabled = false
data.addDataSet(chartDataSet)
}
}
viewPODProgressLineChart.viewProgressLineChart.data = data
}

EXC_BAD_ACCESS (code=1, address=0x) in iOS Danielgindi charts ChartDataSet entries

I am using Charts library (version 3.5.0). Usually the chart is drawn without issue but randomly the app crashes with the following XCode Crash stack screenshot and Crashlytics stack trace screenshot
Class with chart view
class ChartContainerView: UIView {
#IBOutlet var contentView: UIView!
#IBOutlet weak var chartView: CustomLineChartView!
var chartData: LineChartDataSet?
struct TickData: Codable {
let price: Double
let time: Int
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
Bundle.main.loadNibNamed("ChartContainerView", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
chartView.resetChart()
}
func drawChart(withData tickArray: [TickData]) {
chartView.resetChart()
var entries = [ChartDataEntry]()
for (i, tick) in tickArray.enumerated() {
entries.append(ChartDataEntry(x: Double(i), y: tick.price))
}
chartData = LineChartDataSet(entries: entries)
let xValueCount = Double(chartData!.count)
chartView.xAxis.axisMaximum = xValueCount
chartView.setVisibleXRangeMaximum(60.0 * 5)
chartView.setVisibleXRangeMinimum(60.0 * 5)
chartView.setVisibleXRange(minXRange: 5, maxXRange: 2000)
chartView.data = createLineData(lineDataSet: chartData)
chartView.moveViewToX(xValueCount)
chartView.animate(xAxisDuration: 0.5)
}
func createLineData(lineDataSet: LineChartDataSet) -> LineChartData {
lineDataSet.mode = .cubicBezier
lineDataSet.drawCirclesEnabled = true
lineDataSet.circleRadius = 2
lineDataSet.drawCircleHoleEnabled = false
lineDataSet.axisDependency = .right
lineDataSet.lineWidth = 1
lineDataSet.fillAlpha = 0
lineDataSet.highlightLineWidth = 0.3
lineDataSet.drawValuesEnabled = false
lineDataSet.drawFilledEnabled = false
return LineChartData(dataSet: lineDataSet)
}
//This method is called on a background thread
func updateChart(withData tickArray: [TickData]) {
let count = chartData!.count
for (i, tick) in tickArray.enumerated() {
let entry = ChartDataEntry(x: Double(count + i), y: tick.price))
chartData?.append(entry)
}
DispatchQueue.main.async(execute: {
chartView.data?.notifyDataChanged()
chartView.notifyDataSetChanged()
})
}
}
Custom LineChartView
class CustomLineChartView: LineChartView {
override func initialize() {
super.initialize()
renderer = CustomLineChartRenderer(dataProvider: self, animator: _animator, viewPortHandler: _viewPortHandler)
chartDescription?.enabled = false
dragYEnabled = false
scaleYEnabled = false
pinchZoomEnabled = false
doubleTapToZoomEnabled = false
drawGridBackgroundEnabled = false
dragDecelerationFrictionCoef = 0.0
highlightPerTapEnabled = false
autoScaleMinMaxEnabled = true
highlightPerDragEnabled = false
noDataText = ""
leftAxis.enabled = false
legend.enabled = false
dragXEnabled = true
scaleXEnabled = false
xAxis.labelCount = 5
xAxis.labelPosition = .bottom
xAxis.drawAxisLineEnabled = false
xAxis.drawGridLinesEnabled = false
xAxis.granularityEnabled = true
xAxis.granularity = 1.0
rightAxis.labelCount = 5
rightAxis.labelPosition = .outsideChart
rightAxis.drawAxisLineEnabled = false
rightAxis.drawGridLinesEnabled = false
rightAxis.granularityEnabled = true
rightAxis.centerAxisLabelsEnabled = true
rightAxis.granularity = 1.0
rightAxis.drawLimitLinesBehindDataEnabled = false
}
func resetChart() {
clearAllViewportJobs()
removeAnimation()
clearValues()
clear()
data = nil
rightAxis.customYMax = 0
rightAxis.customYMin = 0
zoom(scaleX: 0, scaleY: 0, x: 0, y: 0)
}
}
As this is random, I am unable to find why the entries object's address is corrupted in ChartDataSet.swift

Line chart fill color is faded

I am trying to setup a line chart with one fill colour but for some reason, the fill colour is faded.
Example
Both the random view I have added to middle of screen and the fill colour of the line chart are set to be red, but for some reason the fill colour of the chart is faded.
Can see code here
#IBOutlet var liveChart : LineChartView!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Chart Tests"
configureChart(chart: liveChart)
var xAxis = [String]()
var yAxis = [Double]()
for _ in 0..<10
{
xAxis.append("")
let yVal = Double(randomBetweenNumbers(firstNum: 1.0, secondNum: 100.0))
yAxis.append(yVal)
}
setData(xAxisArray: xAxis, yAxisArray: yAxis, chart: liveChart)
let testView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
testView.center = view.center
testView.backgroundColor = UIColor.red
view.addSubview(testView)
}
func randomBetweenNumbers(firstNum: CGFloat, secondNum: CGFloat) -> CGFloat{
return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum - secondNum) + min(firstNum, secondNum)
}
func configureChart(chart : LineChartView)
{
chart.chartDescription?.text = ""
chart.noDataText = "Loading Data"
chart.backgroundColor = UIColor.clear
chart.drawGridBackgroundEnabled = false
chart.dragEnabled = true
chart.rightAxis.enabled = false
chart.leftAxis.enabled = true
chart.doubleTapToZoomEnabled = false
chart.legend.enabled = false
chart.pinchZoomEnabled = true
chart.highlightPerTapEnabled = false
chart.highlightPerDragEnabled = false
chart.xAxis.enabled = false
chart.leftAxis.drawAxisLineEnabled = false
chart.leftAxis.drawGridLinesEnabled = false
chart.leftAxis.labelCount = 5
chart.leftAxis.forceLabelsEnabled = true
}
func setData(xAxisArray : [String], yAxisArray : [Double], chart : LineChartView)
{
var yVals1 : [ChartDataEntry] = [ChartDataEntry]()
if(xAxisArray.count > 0)
{
for i in 0 ..< xAxisArray.count
{
let chartEntry = ChartDataEntry(x: Double(i), y: yAxisArray[i], data: nil)
yVals1.append(chartEntry)
}
}
let set1: LineChartDataSet = LineChartDataSet(values: yVals1, label: "")
set1.fillColor = UIColor.red
set1.drawFilledEnabled = true
set1.drawCirclesEnabled = false
let data = LineChartData()
data.addDataSet(set1)
liveChart.data = data
}
Is there a way to fix this? Or is this just the way the fill colour of the chart works?
Edit:
I am using
https://github.com/danielgindi/Charts
I assume you use this library: https://github.com/kevinbrewster/SwiftCharts
So the LineChartView automatically set alpha for the fill color: https://github.com/kevinbrewster/SwiftCharts/blob/master/SwiftCharts/LineChart.swift#L758
try to set fillAlpha property of the data set

Hiding separator lines and top border line in iOS Charts

I have a generated chart. I'm trying to make it as simple as possible, thus removing all the unneeded lines, grids, labels etc. I can't get rid of the separator line between the bars and the top and right border lines, as you can see on the picture. I'm using HorizontalBarChart.
Also, here you can see my chart setup code, I tried to disable literally everything:
private func setupCharts(selectedHero: Int) {
classWinrateChart.descriptionText = ""
classWinrateChart.legend.enabled = false
classWinrateChart.drawBordersEnabled = false
classWinrateChart.drawMarkers = false
classWinrateChart.drawValueAboveBarEnabled = false
let chartDataSet = BarChartDataSet(yVals: dataSource, label: "Noaaah")
let chartData = BarChartData(xVals: ["", "", "", "", "", "", "", "", "", ""], dataSet: chartDataSet)
let color = constants.colors[selectedHero]
chartDataSet.colors = [color]
chartDataSet.valueFont = UIFont.systemFontOfSize(13)
//chartDataSet.drawValuesEnabled = false
let yAxis = classWinrateChart.leftAxis
let xAxis = classWinrateChart.rightAxis
yAxis.enabled = false
yAxis.drawLabelsEnabled = false
yAxis.drawAxisLineEnabled = false
yAxis.drawGridLinesEnabled = false
xAxis.enabled = false
xAxis.drawLabelsEnabled = false
xAxis.drawAxisLineEnabled = false
xAxis.drawGridLinesEnabled = false
classWinrateChart.rightAxis.enabled = false
yAxis.axisMaxValue = 100
yAxis.axisMinValue = 0
classWinrateChart.tintColor = colors[selectedHero]
classWinrateChart.drawGridBackgroundEnabled = false
classWinrateChart.data = chartData
}
This may help you :
var viwBar = BarChartView()
viwBar.leftAxis.drawGridLinesEnabled = false
viwBar.rightAxis.drawGridLinesEnabled = false
viwBar.xAxis.drawGridLinesEnabled = false
viwBar.drawGridBackgroundEnabled = false
//removes left and right axis representation
let yaxis = viwBar.getAxis(ChartYAxis.AxisDependency.Left)
yaxis.drawLabelsEnabled = false
yaxis.enabled = false
let xaxis = viwBar.getAxis(ChartYAxis.AxisDependency.Right)
xaxis.drawLabelsEnabled = false
xaxis.enabled = false
check your code, Is it like ?
let xAxis = classWinrateChart.rightAxis
classWinrateChart.rightAxis is rightAxis, not xAxis.