UILabel With Different Colours - swift

I have a label in a custom cell which displays some info. The info will different in every cell and I would like to change the colour of a few 'keywords' inside the label so that they stand out.
I've tried the approach of converting the text to a NSMutableAttributedString and changing the colour of the text at a certain index. However, the location of the keyword in the text is different in every sentence. Is there any way to add something around the keywords so that they can be identified easily?
Edit: This answered my question:
Changing specific text's color using NSMutableAttributedString in Swift

You can do with attirbutedSring. Do not forget change font.
let string1 = "Your string";
let string2 = "your string 2";
let attributedString = NSMutableAttributedString(string: "“\(string1)” \(string2)", attributes: [
.font: UIFont(name: "IBMPlexSans", size: 15.0)!,
.foregroundColor: UIColor(red: 128.0 / 255.0, green: 130.0 / 255.0, blue: 135.0 / 255.0, alpha: 1.0),
.kern: 0.4
])
attributedString.addAttribute(.foregroundColor, value: UIColor(red: 1.0 / 255.0, green: 6.0 / 255.0, blue: 16.0 / 255.0, alpha: 1.0), range: NSRange(location: 0, length: string1.count));
yourLabel.attributedText = attributedString;

Related

Change UILabel attributed String color multiple times

I am new to Swift 5 and am doing my first project.
I want to change the color of some texts inside my label, this is what my label looks like:
"You need to pay attention to blue texts, and even more to red texts. Try again so there is no more blue / red texts"
I want to change all the "blue" to blue, and all the "red" to red. Did some research and this is what I found:
extension NSMutableAttributedString {
func setColor(color: UIColor, forText stringValue: String) {
let range: NSRange = self.mutableString.range(of: stringValue, options: .caseInsensitive)
self.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range)
}
}
let mainString = popUpLabel.text!
let blueString = "màu xanh" //(which is blue)
let redString = "màu đỏ" //(whish is red)
let attributedString = NSMutableAttributedString.init(string: mainString)
attributedString.setColor(color: UIColor(red: 0.24, green: 0.65, blue: 0.96, alpha: 1.00), forText: blueString)
attributedString.setColor(color: UIColor(red: 0.99, green: 0.20, blue: 0.20, alpha: 1.00), forText: redString)
popUpLabel.attributedText = attributedString
And also tried this:
let mainString = popUpLabel.text!
let blueString = "màu xanh" //(which is blue)
let redString = "màu đỏ" //(which is red)
let attributedString = NSMutableAttributedString.init(string: mainString)
let blueRange = (mainString as NSString).range(of: blueString)
let redRange = (mainString as NSString).range(of: redString)
attributedString.addAttributes([NSAttributedString.Key.foregroundColor : UIColor(red: 0.24, green: 0.65, blue: 0.96, alpha: 1.00)], range: blueRange)
attributedString.addAttributes([NSAttributedString.Key.foregroundColor : UIColor(red: 0.99, green: 0.20, blue: 0.20, alpha: 1.00)], range: redRange)
popUpLabel.attributedText = attributedString
Both works pretty well for the first blue and red, but the second blue and red stayed in black and I don't know why.
range(of: finds only the first occurrence of the search string.
A possible solution is Regular Expression, the pattern searches for both red and blue and changes the color accordingly.
let string = "You need to pay attention to blue texts, and even more to red texts. Try again so there is no more blue / red texts"
let pattern = "(red|blue)"
var attributedString = NSMutableAttributedString(string: string)
let regex = try! NSRegularExpression(pattern: pattern)
let matches = regex.matches(in: string, range: NSRange(string.startIndex..., in: string))
for match in matches {
let range = Range(match.range, in: string)!
let color : UIColor
if string[range] == "red" {
color = UIColor(red: 0.99, green: 0.20, blue: 0.20, alpha: 1.00)
} else {
color = UIColor(red: 0.24, green: 0.65, blue: 0.96, alpha: 1.00)
}
attributedString.addAttribute(.foregroundColor, value: color, range: match.range)
}
You also may use html-text converted to attributed string. Look at this answer.
Example from the answer:
let htmlText = "<medium><b><font color='#2f3744'>IPL Tamil Web Series Episode #3 | யாருடா Swetha ? | Tamil Comedy Web Series | Being Thamizhan</font></b></medium> has been succesfully scheduled on <medium><b><font color='#2f3744'>2018-05-23 08:51 PM</font></b></medium>"
let encodedData = htmlText.data(using: String.Encoding.utf8)!
var attributedString: NSAttributedString
do {
attributedString = try NSAttributedString(data: encodedData,
options:
[NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html,
NSAttributedString.DocumentReadingOptionKey.characterEncoding: NSNumber(value: String.Encoding.utf8.rawValue)],
documentAttributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
} catch {
print("error")
}

Creating CGColor from RGB Value

I use the following code to set the background of a viewcontroller
view.wantsLayer = true
let myColor = NSColor(calibratedRed: 50, green: 50, blue: 50, alpha: 1.0)
view.layer?.backgroundColor = myColor.cgColor
But on debugging myColor i get the following color instead of the intended color
Here is the documentation. Anything above 1 is considered as 1. You need to divide each value by 255.
view.wantsLayer = true
let myColor = NSColor(calibratedRed: 50/255, green: 50/255, blue: 50/255, alpha: 1.0)
view.layer?.backgroundColor = myColor.cgColor
Also, check this out -> Link
Range of color components (RGBA) vary between [0,1]
init(red:green:blue:alpha:)
Creates a color object with the specified red, green, blue, and alpha
channel values. This method accepts extended color component values.
If the red, green, blue, or alpha values are outside of the 0-1.0
range,
So you can get cgColor
view.layer?.backgroundColor = NSColor(calibratedRed: 50.0/255.0, green: 50.0/255.0, blue: 50.0/255.0, alpha: 1.0).cgColor

Setting tintColor for Apple Watch complication

I am trying to set the header text color for a Modular Large complication.
I have already customized the watch face to use Multicolor.
However, when I build and run this code, the header text color is still white (which is the default).
Why isn't the color updating?
private func templateForClassModularLarge(className: Schedule) -> CLKComplicationTemplateModularLargeStandardBody {
let template = CLKComplicationTemplateModularLargeStandardBody()
let headerTextProvider = CLKSimpleTextProvider(text: "My Schedule", shortText: "Schedule")
headerTextProvider.tintColor = UIColor(red: 101, green: 153, blue: 255, alpha: 1)
template.headerTextProvider = headerTextProvider
template.body1TextProvider = CLKTimeIntervalTextProvider(startDate: className.start, endDate: className.end)
template.body2TextProvider = CLKSimpleTextProvider(text: className.description, shortText: className.shortDescription)
return template
}
UIColor parameter types are CGFloat, specified as a value from 0.0 to 1.0.
Because your RGB parameters are greater than 1, the color ends up being white, which would be:
UIColor(red: 1, green: 1, blue: 1, alpha: 1)
To fix this issue, simply change your tintColor to
headerTextProvider.tintColor = UIColor(red: 101/255, green: 153/255, blue: 255/255, alpha: 1)

Does the legend limit the number of titles?

I am using iso-charts to try and draw a pie chart in an iOS app.
No matter what I try, I can't seem to get the full number of titles to draw in the legend.
I have my data set up as:
ages = ["18-", "25-", "35-", "45-", "55-", "65-", "75+"]
agePercentages = [10.0, 20.0, 30.0, 5.0, 10.0, 45.0, 120.0]
My code to setup the pieChart as:
func setPieDefaults(myPieChart: PieChartView) -> PieChartView {
myPieChart.frame = CGRectMake(0, 0, UIScreen.mainScreen().bounds.size.width, UIScreen.mainScreen().bounds.size.width*0.5)
myPieChart.usePercentValuesEnabled = true
myPieChart.holeTransparent = true
myPieChart.holeColor = UIColor.darkPurpleColor()
myPieChart.backgroundColor = UIColor.darkPurpleColor()
myPieChart.rotationAngle = 0.0
myPieChart.rotationEnabled = true
myPieChart.centerTextFont = UIFont(name: "HelveticaNeue-Bold", size:20)!
myPieChart.descriptionText = ""
myPieChart.centerText = "%"
myPieChart.centerTextColor = UIColor.whiteColor()
myPieChart.drawHoleEnabled = true
myPieChart.noDataText = "Loading Data ..."
let legend = myPieChart.legend
legend.font = UIFont(name: "Arial", size: 11)!
legend.textColor = UIColor.whiteColor()
legend.position = .RightOfChart
legend.form = .Circle
return myPieChart
}
And ..
func setChart(dataPoints: [String], values: [Double], myPieView: PieChartView) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = ChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
var colors = [UIColor]()
switch myPieView {
case genderPieChartView:
colors = [UIColor.blueColor(), UIColor.pinkColor()]
default:
colors = ChartColorTemplates.colorful()
}
let pieChartDataSet = PieChartDataSet(yVals: dataEntries, label: nil)
pieChartDataSet.sliceSpace = 3.0
pieChartDataSet.colors = colors
let pieChartData = PieChartData(xVals: dataPoints, dataSet: pieChartDataSet)
myPieView.animate(xAxisDuration: 2, yAxisDuration: 2)
let pFormatter = NSNumberFormatter()
pFormatter.numberStyle = .PercentStyle
pFormatter.maximumFractionDigits = 0
pFormatter.percentSymbol = ""
pFormatter.multiplier = 1
pieChartData.setValueFormatter(pFormatter)
pieChartData.setValueFont(UIFont(name: "HelveticaNeue-Bold", size: 11)!)
pieChartData.setValueTextColor(UIColor.whiteColor())
myPieView.data = pieChartData
myPieView.drawSliceTextEnabled = false
}
But it won't print any more than 5 of the labels. It's returning the pie-slices perfectly. But not the labels in the legend.
Am I doing something wrong? Thanks in advance for letting me know.
Solved.
In reading the framework docs for the Android version a little better:
The number of entries the automatically generated legend contains
depends on the number of different colors (across all DataSet objects)
as well as on the DataSet labels. The labels of the Legend depend on
the labels set for the used DataSet objects in the chart. If no labels
for the DataSet objects have been specified, the chart will
automatically generate them. If multiple colors are used for one
DataSet, those colors are grouped and only described by one label.
I realised I needed to increase the number of colours in the ChartColorTemplate.colorful() definition to match the number of labels I was trying to use. The current example code comes with only 5 colours defined.
public class func colorful () -> [UIColor]
{
return [
UIColor(red: 193/255.0, green: 37/255.0, blue: 82/255.0, alpha: 1.0),
UIColor(red: 255/255.0, green: 102/255.0, blue: 0/255.0, alpha: 1.0),
UIColor(red: 245/255.0, green: 199/255.0, blue: 0/255.0, alpha: 1.0),
UIColor(red: 106/255.0, green: 150/255.0, blue: 31/255.0, alpha: 1.0),
UIColor(red: 179/255.0, green: 100/255.0, blue: 53/255.0, alpha: 1.0),
UIColor(red: 200/255.0, green: 100/255.0, blue: 53/255.0, alpha: 1.0), // added colour
UIColor(red: 150/255.0, green: 150/255.0, blue: 70/255.0, alpha: 1.0), // added colour
UIColor(red: 84/255.0, green: 78/255.0, blue: 53/255.0, alpha: 1.0), // added colour
]
}
If you have the same problem, then define a lot more colours to meet the needs of the maximum number of labels needed. This will also solve a problem if you try and word-wrap the legend (which I was also facing).

set a text output colour

I have a textfield that has a sum attached to the output
just wondering how do I write a line that has the effect of:
If the final figure is less then zero the text colour is red
and if the output is positive figure text is another colour.
txtsum.textColor = UIColor (red: 255.0, green: 0.0, blue: 0.0, alpha: 1.0)
This works to set the colour as red.
Just don’t know how to write a statement( if thats what I need) guessing its if and else statement
This my output line
txtsum!.text = NSString(format: "%.2f", sum1)
It is indeed a simple if statement. Run this every time you change the text of the text field:
if sum1 < 0 {
txtsum.textColor = UIColor(red: 255.0, green: 0.0, blue: 0.0, alpha: 1.0)
}
else {
txtsum.textColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
}