Formatting bar chart x-axis values, bars, and label - swift

I have this bar chart, it has some formatting issues:
I'd like to address these:
there's strange numbers inside the bars. They could disappear, that would be quite happy.
there's also strange, but different numbers above the bars. These could be the actual number.
the chart label "recent Apps Data" could look more primary (bigger, bold-italic for example)
the dates in the x-axis are .. kinda close. Not sure how to handle that one.
here's how I'm drawing these:
func setBarChart (data: [(String,[Double])], label: String, xLabels: [String]) {
var entries: [BarChartDataEntry] = []
for (index, tuple) in data.enumerated() {
entries.append(BarChartDataEntry(x: Double(index), yValues: tuple.1))
}
let set = BarChartDataSet(values: entries, label: DataViewController.constants.labelDate)
set.setColor(UIColor.orange)
let data = BarChartData(dataSets: [set])
barChart.data = data
barChart.chartDescription?.text = label
barChart.xAxis.valueFormatter = IndexAxisValueFormatter(values: xLabels)
barChart.xAxis.granularity = 1
let legendEntry = LegendEntry()
legendEntry.formColor = UIColor.orange
legendEntry.label = "mean performance"
barChart.legend.setCustom(entries: [legendEntry]);
barChart.notifyDataSetChanged()
}

I do not know the answer to your first three questions, however, I had a similar problem to the one you describe in your fourth question. I discovered two options to overcome the problem of overlaying labels:
You could show labels' texts in two lines by adding \n in the middle of the string (for example, "2018\n07-23"). This would reduce the width of the label and thus they would not cover each other.
The second option could be to reduce the amount of bars shown in the chart. You could achieve this by using setVisibleXRangeMaximum (more on this here).
Good luck!

Related

Highlights on multiple lines LineChart

I am using danielgindi/Charts library.
I have a LineChart with two data sets, I want only one highlight line to highlight both data sets instead of individual highlights for each.
For example, as the picture shows, there are two highlight lines for each line(dataset), but I want only one highlight line can highlight both lines(datasets) and select values similar to this.
Here is the code I have for reference:
let set1 = LineChartDataSet(entries: set1Values, label: "first")
set1.highlightLineWidth = 1
set1.highlightEnabled = true
let set2 = LineChartDataSet(entries: set2Values, label: "second")
set2.highlightLineWidth = 1
set2.highlightEnabled = true
let data = LineChartData(dataSets: [set1, set2])
myChartView.data = data
Thank you for your help.
Why you persist in highlight a line?
I'm not sure but I think you should highlight your chart's container so that checking every line.

How to edit NSAttributedstring background color size and position with Swift

in my app I have a feature where user can add background color to text
So, I added .backgroundColor attribute and it works but background position is different for different fonts. Is there a way to edit string background size and position or should I try to edit ttf fonts instead?
Thanks
Edit - Code:
I tried 2 methods
First one excluding spaces:
var startIndex = self.text.startIndex
while let r = self.text.range(of: "\\S+", options: .regularExpression, range: startIndex..<self.text.endIndex) {
customizedText.addAttribute(.backgroundColor, value: highlightColor, range: NSRange(r, in: self.text))
startIndex = r.upperBound
}
Result excluding spaces
Another one is simply add background color for every char:
customizedText.addAttribute(.backgroundColor, value: highlightColor, range: range)
Result: whole string
Ass you can see, it's doesn't look good with any alignment but Left.
We could probably live with this but problem is what it looks horribly wrong with some other fonts
Examples:
Gayatri Anton
Another example of what is now(red) and what I want(white):
Desired result
Any ideas?
Thanks

How do I obtain the x-value of highlighted point when using Charts UI?

I have a variable that changes depending on the x-value of the point as defined by the user on the graph. How do I go about this? I need the x-coordinate of the point in order to change another view.
Right now, I have a simple CombinedChart. What I want is when apoint is highlighted, the x-coordinate is then obtained, and this changes a label. (For example, if the person clicks on (1,3), the label will display "1"
I have tried:
Global.chiller1x = Double(chiller1Chart.xAxis.labelPosition.rawValue)
print(String(format: "%.2f", Global.chiller1x ?? 0))
I have also looked at getMarkerPosition, etc but none seem to have worked.
You can use the Chart Delegate (ChartViewDelegate) method chartValueSelected() to capture user click with X & Y value on that touch points.
Use Below Method:
extension LineChartViewController: ChartViewDelegate{
public func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
//Print Value like entry.x & entry.y
}
}
Hope this will helps you to get user touch with X & Y values.

UILabel splitting in the middle of words (or how to get proper word wrapping)

I'm trying to fit some text into a fixed-width label (actually the width depends on the screen size, but cannot change within the app), and expect UIKit to cleverly use a combination of font resizing and word-wrapping to get the proper result. However, it doesn't seem to work that way. Considering a UILabel with the following constraints:
aspect ratio = 1:1
label.width = 0.7 * parentView.width (all other relevant constraints set, no errors or warnings in IB)
and the following code:
label.font = label.font.withSize(100)
label.adjustsFontSizeToFitWidth = true
label.lineBreakMode = .byClipping
label.numberOfLines = 0
label.text = "Shooter team"
I would be hoping that it would resize the text and make it fit into two lines: "Shooter" and "team" (or, since the text could be anything, split it properly into words). However, when I set label.lineBreakMode to .byWordWrapping, it doesn't resize the text at all and so only one big letter is displayed (note: I'm using a big font size for it to resize because I can't know in advance how big the text is going to be, since the size depends on the screen size). Any other value for .lineBreakMode results in the text being resized but split into "Shoote" and "r team", which looks dumb. Changing autoshrink to e.g. Minimum font size = 8 doesn't seem to have any effect. See screenshot below.
Any suggestion of how I can get the proper splitting/resizing? I may have used the wrong terms for my searches but I haven't found any answer :-|
(Note: there will be a different question about how I can get the border of the encompassing view to be a nice circle prior to the view being displayed :-| )
First, to take advantage of adjustsFontSizeToFitWidth, you must also give it a scale factor (the smallest size you're willing to let the label shrink to). So if, for example, your label's font is sized at 30, you could let it shrink down to 24:
someLabel.font = UIFont(name: "someFont", size: 30)
someLabel.adjustsFontSizeToFitWidth = true
someLabel.minimumScaleFactor = (24/30)
Second, you may want to consider using an attributed title for your label to take advantage of paragraph styling. Paragraph styling lets you play with hyphenation rules:
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.hyphenationFactor = 1.0
let attributedTitle = NSAttributedString(string: "Shooter team", attributes: [NSAttributedString.Key.foregroundColor: UIColor.red, NSAttributedString.Key.paragraphStyle: paragraphStyle])
someLabel.attributedText = attributedTitle
For lack of a better solution I've written the following function that empirically tries to find a font size that doesn't split a word in the middle. It's hackish but at least it works... Comments, suggestions or any better solution welcome!
func findFittingFont(for label: String) -> UIFont {
// note: the 'split' function is a personal addition that splits a string on a regex
// in this case, split between a non-word char and a word char
let words = label.split(pattern: "(?<=\\W)(?=\\w)")
var font = myLabel.font!
// the width we don't want to overflow
let maxWidth = myLabel.frame.width
var fontSize = myLabel.frame.height
var tooBig: Bool
repeat {
tooBig = false
font = font.withSize(fontSize)
// check for each word whether the rendered width is larger than the max width
for word in words {
// calculate the rendered width with the current font
let width = (word as NSString).size(withAttributes: [.font: font]).width
if width > maxWidth {
tooBig = true
// decrease the size by a factor
fontSize *= 0.9
break
}
}
// go on as long as there's an overflowing word
}
while tooBig
return font
}

IOS-Charts set maximum visible x axis values

I'm using ios-charts (https://github.com/danielgindi/Charts). I have a LineChartView with 12 values in the x axis.
This however is far too many to see at the same time, so I want to display only 5 and then let the user drag to the right to see the next.
I've tried this:
let chart = LineChartView()
chart.dragEnabled = true
chart.setVisibleXRangeMaximum(5)
let xAxis = chart.xAxis
xAxis.axisMinValue = 0
xAxis.axisMaxValue = 5.0
xAxis.setLabelsToSkip(0)
But still see all 11 values at the time. How can I only see 5?
I finally got it!
The correct answer is:
chart.setVisibleXRangeMaximum(5)
This however needs to be set after the data has been set in the chart (not in a configure before)
This did the trick for me
You should set the X axis's labelCount property of the chart view.
In objc,like this
_chartView.xAxis.labelCount = 5;
Swift
chartView.xAxis.labelCount = 5
Here is my finding!!
you don't need to really use label count
if you are using DefaultAxisValueFormatter, NEVER use this. a lot of errors pop ! just use no2.
chart.setVisibleXRangeMaximum(number) will do.
please put this after chart data setting here you can see detail
combinedChartView.data = combineData. //this need to come first
combinedChartView.setVisibleXRangeMaximum(2) //after data setting