I am using danielgindi/Charts library. In my main view controller I have table view with 3 prototype cell. One of them is for bar chart, second one is for line chart and third one is for pie chart. There are also 3 dequeue reusable cell method and charts configure methods are inside of them. When I first execute application all my bar charts are drawn without any problem. However, when I add new charts or when I scroll (I am not sure but I think one of them lead weird problem) bar chart view looks weird as it shown below image.
It is shown like second one when I first execute program but after some scrolling or adding new charts it looks first one. Every data set cover x axis. Following is my configureBarChart method.
func configureBarChart(xTitle: IndexAxisValueFormatter, index: Int, chartData: BarChartData, chartType: String) {
barChartView.data?.setDrawValues(false)
barChartView.doubleTapToZoomEnabled = false
barChartView.chartDescription?.enabled = false
barChartView.animate(xAxisDuration: 1)
barChartView.xAxis.drawGridLinesEnabled = false
barChartView.xAxis.valueFormatter = xTitle
barChartView.xAxis.labelCount = index
barChartView.rightAxis.enabled = false
barChartView.xAxis.drawGridLinesEnabled = false
barChartView.xAxis.labelPosition = .bottom
barChartView.xAxis.centerAxisLabelsEnabled = true
barChartView.xAxis.granularity = 1
let leftAxisFormatter = NumberFormatter()
leftAxisFormatter.maximumFractionDigits = 1
barChartView.leftAxis.spaceTop = 0.35
barChartView.leftAxis.axisMinimum = 0
barChartView.leftAxis.drawGridLinesEnabled = false
barChartView.rightAxis.enabled = false
var groupSpace = 0.0
var barSpace = 0.0
var barWidth = 0.0
if (chartData.dataSetCount == 1) {
groupSpace = 0.3
barSpace = 0.0
barWidth = 0.7
} else if (chartData.dataSetCount == 2) {
groupSpace = 0.3
barSpace = 0.05
barWidth = 0.3
} else if (chartData.dataSetCount == 3) {
groupSpace = 0.25
barSpace = 0.05
barWidth = 0.2
} else if (chartData.dataSetCount == 4) {
groupSpace = 0.2
barSpace = 0.05
barWidth = 0.15
}
let groupCount = index
let startYear = 0
chartData.barWidth = barWidth;
barChartView.xAxis.axisMinimum = Double(startYear)
let gg = chartData.groupWidth(groupSpace: groupSpace, barSpace: barSpace)
if (chartType == "clustered") {
barChartView.xAxis.axisMaximum = Double(startYear) + gg * Double(groupCount)
chartData.groupBars(fromX: Double(startYear), groupSpace: groupSpace, barSpace: barSpace)
} else {
barChartView.xAxis.axisMaximum = Double(startYear) + 1 * Double(groupCount)
}
barChartView.setScaleEnabled(false)
if xTitle.values.count >= 10 {
barChartView.setVisibleXRangeMaximum(12)
} else {
barChartView.setVisibleXRangeMaximum(Double(xTitle.values.count)) // When too many data comes I limit it so data's are not covering each other.
}
}
I am also using that bar chart for grouped bar chart that is why there is some barSpace and barWidth code. What could be the reason of changing behavior of chart and how can I fix it ?
Edit: Here is my cellForRowAt method and getting data of bar chart
if MainGrafikVC.barChartDataArray[indexPath.row].dataSetCount != 0 {
cell.barChartView.data = MainGrafikVC.barChartDataArray[indexPath.row]
cell.configureBarChart(xTitle: MainGrafikVC.xTitleArray[indexPath.row], index: MainGrafikVC.barChartDataArray[indexPath.row].getDataSetByIndex(0).entryCount, chartData: MainGrafikVC.barChartDataArray[indexPath.row], chartType: Servisler.servisListesi[MainGrafikVC.indexler[indexPath.row]].chartType)
}
if x10.count > 0 {
var barChartEntry10 = [BarChartDataEntry]()
for i in 0..<x10.count {
let value = BarChartDataEntry(x: Double(i), y: Double(x10[i]) ?? 0.0)
barChartEntry10.append(value)
}
let bar10 = BarChartDataSet(values: barChartEntry10, label: "10")
bar10.colors = ChartColorTemplates.vordiplom()
dataSets.append(bar10)
}
let data = BarChartData(dataSets: dataSets)
MainGrafikVC.barChartDataArray.append(data)
I think the problem is about setVisibleXRangeMaximum because when I comment it everything looks same. However, I need to set visible x axis what could be alternative of it?
Related
Hi using cocoapods charts. Trying to pivot bar-chart from right to left. with hidden bottom x-axis values.
Charts
https://cocoapods.org/pods/Charts
Below is code which I tried.
totalExpenseAmount = 33 -> Double
timesheetAmount = 300 -> Double
self.setBarChart(expenseAmount: totalExpenseAmount, timesheetAmount: totalTimesheetAmount)
// MARK: - DRAW CHART
func setBarChart(expenseAmount: Double, timesheetAmount: Double){
var dataEntries: [BarChartDataEntry] = []
barChartView.backgroundColor = UIColor.white
for i in 0..<2 {
let dataEntry = BarChartDataEntry(x: Double(i), y: i == 0 ? expenseAmount : timesheetAmount)
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(entries: dataEntries)
chartDataSet.colors = [UIColor.init(hexString: "#008CA1") , UIColor.init(hexString: "#EF776C")]
let chartData = BarChartData()
chartData.barWidth = Double(0.25)
chartData.append(chartDataSet)
chartData.setDrawValues(true)
barChartView.xAxis.labelPosition = .bottom
barChartView.xAxis.drawGridLinesEnabled = false
barChartView.chartDescription.enabled = false
barChartView.legend.enabled = false
barChartView.rightAxis.enabled = false
barChartView.leftAxis.drawGridLinesEnabled = true
barChartView.leftAxis.drawLabelsEnabled = true
barChartView.data = chartData
barChartView.leftAxis.spaceBottom = 0.0
barChartView.notifyDataSetChanged()
}
I tried to pivot bar chart from right to left. with Hidden bottom x-axis values.
Issue is second bar chart for 33 value not shown.
Unable to drawn bar chart from right to left.
Unable to hide the x-axis labels values ( -0.3 0.0 0.3 0.6 0.9 1.2 1.5)
Any one worked on charts please provide your inputs, Its deeply appreciated your input's.
I have made a bar chart with 6 groups and I have manage to hack my way into centering them exactly below each group. Now, the problem is that the value inside of each label is repeating.
My values array contains 6 different values and my label count is on 7. The labelCount needed to be 7 in order for chart to center them correctly. More over, I did set this value to 6 too, thinking that there is an indexing issue when the value formatter is picking values, and labels are still repeating.
I have already tried changing the granularity to all sorts of values and it does not seam to work. Also I fiddled around toggling granularity to true or false, but it does not work either.
Screenshot
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
lazy var barChart: BarChartView = {
let chart = BarChartView()
chart.translatesAutoresizingMaskIntoConstraints = false
var inComing = [BarChartDataEntry]()
var outgoing = [BarChartDataEntry]()
for i in 0..<6 {
let entry = BarChartDataEntry(x: Double(i), y: Double.random(in: 10..<100))
inComing.append(entry)
}
for i in 6..<12 {
let entry = BarChartDataEntry(x: Double(i), y: Double.random(in: 10..<100))
outgoing.append(entry)
}
let set1 = BarChartDataSet(entries: inComing, label: "Incoming")
let set2 = BarChartDataSet(entries: outgoing, label: "Outgoing")
let incomingColor = UIColor(red: 51 / 255, green: 51 / 255, blue: 51 / 255, alpha: 1)
set1.colors = [incomingColor]
let outgoingColor = UIColor(red: 153 / 255, green: 0, blue: 0, alpha: 1)
set2.colors = [outgoingColor]
let data = BarChartData(dataSets: [set1, set2])
let barWidth = 0.004
let barSpace = 0.007
let groupSpace = 0.032
let groupCount = 6
data.barWidth = barWidth
let gg = data.groupWidth(groupSpace: groupSpace, barSpace: barSpace)
chart.data = data
chart.xAxis.axisMinimum = 0
chart.xAxis.axisMaximum = gg * Double(groupCount)
set1.drawValuesEnabled = false
set2.drawValuesEnabled = false
chart.xAxis.drawGridLinesEnabled = false
chart.xAxis.drawAxisLineEnabled = true
chart.drawBordersEnabled = true
let formater = IndexAxisValueFormatter.with(values: months)
chart.xAxis.centerAxisLabelsEnabled = true
chart.xAxis.setLabelCount(7, force: true)
chart.xAxis.granularityEnabled = true
chart.xAxis.axisMaxLabels = 6
chart.xAxis.axisMinLabels = 0
chart.xAxis.labelPosition = .bottom
chart.xAxis.valueFormatter = formater
chart.xAxis.drawLimitLinesBehindDataEnabled = false
chart.leftAxis.drawGridLinesEnabled = false
chart.leftAxis.drawAxisLineEnabled = false
chart.rightAxis.drawGridLinesEnabled = false
chart.rightAxis.drawAxisLineEnabled = false
chart.rightAxis.drawLabelsEnabled = false
data.groupBars(fromX: 0, groupSpace: groupSpace, barSpace: barSpace)
chart.drawGridBackgroundEnabled = false
chart.legend.enabled = false
chart.notifyDataSetChanged()
return chart
}()
I have this simple implementation of charts for iOS. And I'm looking for a way to align the labels at the center of each bar.
What I've accomplished so far was to position the labels inside each bar. I'm stuck at this point, as I don't see any way to achieve centering the label.
Here is a screenshot of what I've accomplished.
A snippet of the code used to setup this view.
func prepareHorizontalBarChart() {
var entries1 = [BarChartDataEntry]()
var entries2 = [BarChartDataEntry]()
var entries3 = [BarChartDataEntry]()
let values:[String] = ["1/22", "1/25", "1/30"]
let bar1 = BarChartDataEntry(x: Double(0), y: Double(4), icon: nil, data: "1/22" as AnyObject)
entries1.append(bar1)
let bar2 = BarChartDataEntry(x: Double(1), y: Double(6))
entries2.append(bar2)
let bar3 = BarChartDataEntry(x: Double(2), y: Double(2))
entries3.append(bar3)
let set1 = BarChartDataSet(values: entries1, label: "test")
set1.drawIconsEnabled = false
let set2 = BarChartDataSet(values: entries2, label: "test")
set1.drawIconsEnabled = false
let set3 = BarChartDataSet(values: entries3, label: "test")
set1.drawIconsEnabled = false
set1.colors = [UIColor.purple]
set2.colors = [UIColor.magenta]
set3.colors = [UIColor.red]
let data = BarChartData(dataSets: [set1, set2, set3])
data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10))
data.barWidth = 0.2
let formatter = NumberFormatter()
formatter.numberStyle = .none
formatter.maximumFractionDigits = 0
formatter.multiplier = 1.0
let defaultValueFormatter = DefaultValueFormatter(formatter: formatter)
data.setValueFormatter(defaultValueFormatter)
horizontalBarChart.zoomOut()
horizontalBarChart.fitBars = true
horizontalBarChart.data = data
horizontalBarChart.xAxis.drawGridLinesEnabled = false // disable horizontal grid lines
// horizontalBarChart.xAxis.enabled = false
horizontalBarChart.chartDescription?.enabled = false
horizontalBarChart.xAxis.valueFormatter = IndexAxisValueFormatter(values: values)
horizontalBarChart.xAxis.labelPosition = .bottom
horizontalBarChart.rightAxis.enabled = false
horizontalBarChart.leftAxis.axisMinimum = 0
horizontalBarChart.legend.verticalAlignment = .top
horizontalBarChart.legend.horizontalAlignment = .center
horizontalBarChart.legend.orientation = .vertical
horizontalBarChart.drawValueAboveBarEnabled = false
horizontalBarChart.legend.enabled = false
horizontalBarChart.animate(xAxisDuration: 2.0, yAxisDuration: 2.0)
}
Goto Charts and look for HorizontalBarChartRender class, find a method called draw values and changed value for text alignment to center.
or: Search for these two lines
let x = transformed[k].x + (drawBelow ? negOffset : posOffset)
replace it with
let x = buffer.rects[k].origin.x + buffer.rects[k].size.width / 2.2
if !viewPortHandler.isInBoundsTop(rect.origin.y) { break }
comment out this line
After migrating to Swift 3, my line chart is displayed with strange values in the y-axis. I am not sure if it is the range or the dataset that has the problem. But I checked and the y values seem to be correct.
The chart itself is also displayed as a blue rectangle instead of a line chart (I am assuming because of the wrong y values)
Would any one have an idea what could be wrong by looking at this chart?
Chart
Update:
I was able to pinpoint the problem to the right axis axisMinimum and axisMaximum that do not get set properly. When I use the same code for the left axis, it works perfectly.
here is the code for setting up:
class func newLineChartViewWithXValsAndDataSets(frame: CGRect, xVals: [String], dataSets: [SVLineChartDataSet]?, maximum: ChartDataEntry?, minimum: ChartDataEntry?) -> LineChartView {
let lineChartView = LineChartView(frame: frame)
let chartData = LineChartData(dataSets: dataSets)
let margin: CGFloat = 6
lineChartView.doubleTapToZoomEnabled = false
lineChartView.dragEnabled = false
lineChartView.drawGridBackgroundEnabled = false
lineChartView.drawBordersEnabled = false
lineChartView.legend.textColor = UIColor.sharevilleLightGrey
lineChartView.xAxis.labelPosition = .bottom
lineChartView.xAxis.labelTextColor = UIColor.sharevilleLightGrey
lineChartView.xAxis.avoidFirstLastClippingEnabled = true
lineChartView.xAxis.drawGridLinesEnabled = false
lineChartView.xAxis.axisLineColor = UIColor.sharevilleTouchGrey
lineChartView.xAxis.valueFormatter = LineChartDateFormatter(dates: xVals)
lineChartView.xAxis.setLabelCount(3, force: true)
lineChartView.leftAxis.axisLineColor = UIColor.sharevilleTouchGrey
//lineChartView.leftAxis.drawLabelsEnabled = false
//lineChartView.leftAxis.drawAxisLineEnabled = false
lineChartView.leftAxis.spaceTop = margin
lineChartView.leftAxis.spaceBottom = margin
lineChartView.leftAxis.resetCustomAxisMax()
lineChartView.leftAxis.resetCustomAxisMin()
lineChartView.rightAxis.labelTextColor = UIColor.sharevilleDarkGrey
lineChartView.rightAxis.axisLineColor = UIColor.sharevilleTouchGrey
lineChartView.rightAxis.gridColor = UIColor.sharevilleTouchGrey
lineChartView.rightAxis.labelPosition = .insideChart
lineChartView.rightAxis.drawLabelsEnabled = false
lineChartView.rightAxis.drawAxisLineEnabled = false
lineChartView.rightAxis.spaceTop = margin
lineChartView.rightAxis.spaceBottom = margin
// if we have no maximum and minimumvalue return the linechart directly
guard let maximum = maximum, let minimum = minimum else {
return lineChartView
}
//let absMinMax = abs(maximum.y - minimum.y)
//let visibleYRangeMaxium = max(absMinMax,1) * 1.2
// print("visibile Y Range")
// print(visibleYRangeMaxium)
//lineChartView.setVisibleYRangeMaximum(visibleYRangeMaxium, axis: YAxis.AxisDependency.left)
lineChartView.leftAxis.axisMinimum = minimum.y
lineChartView.leftAxis.axisMaximum = maximum.y
//lineChartView.rightAxis.axisMinimum = minimum.y
//lineChartView.rightAxis.axisMaximum = maximum.y
lineChartView.animate(xAxisDuration: 1, easingOption: .easeInCubic)
print("LinChartView.data= ", lineChartView.data)
lineChartView.chartDescription?.text = ""
lineChartView.backgroundColor = .white
if let dataSets = dataSets {
for dataSet in dataSets {
if dataSet.isLineChartViewHighLowEnabled {
DispatchQueue.main.async {
self.drawLineChartValueView(lineChartView, dataEntry: maximum)
self.drawLineChartValueView(lineChartView, dataEntry: minimum)
}
}
}
}
lineChartView.data = chartData
return lineChartView
}
I don't see you set your data set axisDependency to right axis.
I experience a number of issues with the horizontal bar chart since I updated to the last version of ios-chart (3.0.0).
First thing is that I had labels for the x axis on the charts. With the new version of ios-charts I had to write my own formatter nevertheless only every second label get displayed now. The second problem is that the bar does not reach the value indicated on the y-axis. What I mean by that is that if I give the bar a value of 4 the height of the bar is actually not long enough to reach the 4.0 label on the y-axis. Those 2 issues are illustrated in this picture.
picture of the problems
Here is my code for the value formatter:
#objc(BarChartFormatter)
public class BarChartFormatter: NSObject, IAxisValueFormatter{
var labelArray : [String] = ["text1", "text2", "text3", "text4", "text5", "text6", "text7", "text8", "text9", "text10"]
public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
return labelArray[Int(value)]
}
}
And here is the code for the bar chart
horizontalBarChartView.noDataText = "You need to provide data for the chart."
horizontalBarChartView.isUserInteractionEnabled = false
horizontalBarChartView.drawGridBackgroundEnabled = false
horizontalBarChartView.drawValueAboveBarEnabled = false
horizontalBarChartView.legend.enabled = false
horizontalBarChartView.drawBarShadowEnabled = false
horizontalBarChartView.chartDescription?.text = ""
horizontalBarChartView.setExtraOffsets(left: 0, top: 0, right: 0, bottom: 0)
// Right y axis
let barRightAxis = horizontalBarChartView.leftAxis
barRightAxis.drawGridLinesEnabled = false
barRightAxis.enabled = false
let formato:BarChartFormatter = BarChartFormatter()
let xaxis:XAxis = XAxis()
// Left y axis
let barLeftAxis = horizontalBarChartView.rightAxis
let count = 5
barLeftAxis.setLabelCount(count, force: true)
barLeftAxis.drawGridLinesEnabled = false
barLeftAxis.axisLineWidth = 2
barLeftAxis.axisLineColor = UIColor.white
barLeftAxis.labelTextColor = UIColor.white
barLeftAxis.axisMinimum = 0.0
barLeftAxis.axisMaximum = 4.0
barLeftAxis.granularityEnabled = true
barLeftAxis.granularity = 1.0
barLeftAxis.decimals = 0
// x axis
let barXaXis = horizontalBarChartView.xAxis
barXaXis.drawGridLinesEnabled = false
barXaXis.axisLineColor = UIColor.white
barXaXis.axisLineWidth = 2
barXaXis.labelTextColor = UIColor.white
barXaXis.labelPosition = .bottomInside
barXaXis.granularityEnabled = true
barXaXis.granularity = 1.0
barXaXis.decimals = 0
var dataEntries: [BarChartDataEntry] = []
var colors: [UIColor] = []
let theScoreVec = [1.0, 2.0, 3.0, 4.0, 3.0, 0.0, 2.0, 0.0, 1.0, 4.0]
for i in 0..<10 {
let theScore = theScoreVec[i]
if (theScore == 0.0){
colors.append(UIColor.clear)
let dataEntry = BarChartDataEntry(x: Double(i), y : Double(4.0))
dataEntries.append(dataEntry)
} else {
colors.append(UIColor.red)
let dataEntry = BarChartDataEntry(x: Double(i), y: Double(theScore))
dataEntries.append(dataEntry)
}
}
xaxis.valueFormatter = formato
barXaXis.valueFormatter = xaxis.valueFormatter
for i in 0..<10{
formato.stringForValue(Double(i), axis: xaxis)
}
xaxis.valueFormatter = formato
barXaXis.valueFormatter = xaxis.valueFormatter
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Completion")
chartDataSet.colors = colors
let chartData = BarChartData(dataSet: chartDataSet)
chartData.setDrawValues(false)
horizontalBarChartView.data = chartData
Here I also use some kind of hack because when one enters a value of 0.0 for a BarChartDataEntry the bars and the x axis have a significant offset. Therefore I create bars with a fake value and give them a transparent color.
Do one you had a similar issue with the library and know where it comes from ? Or maybe has even solved it ?
Thanks in advance for the help.