Can't change Paragraph attributes and String Attributes at the same time - swift

I can get either the NSMutableParagraphStyle line spacing working OR the NSMutableAttributedString to be the correct font,color and size, but I can't get them both at the same time.
let style = NSMutableParagraphStyle()
style.lineSpacing = 5
let attributes = [NSParagraphStyleAttributeName : style]
aboutScrollable.attributedText = NSAttributedString(string: aboutScrollable.text, attributes:attributes)
let myString:NSString = aboutScrollable.text as NSString
var myMutableString = NSMutableAttributedString()
myMutableString = NSMutableAttributedString(string: myString as String, attributes: [NSFontAttributeName:UIFont(name: "Geomanist-regular", size: 12.0)!])
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor(red: 30/255, green: 30/255, blue: 30/255, alpha: 1), range: NSRange(location: 0,length: aboutScrollable.text.characters.count))
// set label Attribute
aboutScrollable.attributedText = myMutableString; NSAttributedString(string: aboutScrollable.text, attributes:attributes)

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")
}

iOS change the color of links for uilabel when using NSAttributedString

I'm using a uilabel and adding a link to by using NSAttributedString
let attributedText = NSMutableAttributedString(string: "http://www.google.com")
attributedText.addAttributes([NSAttributedString.Key.link: "https://www.google.com"], range: NSRange(location: 0, length: 21))
attributedText.addAttributes([NSAttributedString.Key.foregroundColor: UIColor.red], range: NSRange(location: 0, length: 21))
label.attributedText = attributedText
label.tintColor = UIColor.red
How can get the link to be another color other than the other default blue link color provided by the UIKit framework.
Note: I do not want to use UITextView or UIWebView
let attributedText = "http://www.google.com"
let multipleAttributes: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.foregroundColor: UIColor.red,
NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue ]
let attributeString = NSAttributedString(string: attributedText, attributes: multipleAttributes)
// set attributed text on a UILabel
label.attributedText = attributeString

Why are NSAttributedString's attributes influencing other AttributedStrings?

In this case I'm setting a UILabel's attributedText with a combined NSAttributedString with different attributes for each line, and for some reason some AttributedString attributes influence the other AttributedStrings, but I thought their attributed are bound to the range of that particular AttributedString. I'm basically expecting that the NSAttributedString automatically gets its range set up when I append it to the NSMutableAttributedString.
Am I wrong?
In this case the shadows applies to the other appended AttributedStrings, in another case it is the bold font that overrides all fonts to come in the next AttributedStrings. Strange.
Here is some sample code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var textLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
textLabel.numberOfLines = 0
textLabel.lineBreakMode = .byWordWrapping
let myShadow = NSShadow()
myShadow.shadowBlurRadius = 3
myShadow.shadowOffset = CGSize(width: 3, height: 3)
myShadow.shadowColor = UIColor.gray
let attributedText = NSMutableAttributedString(string: "")
let fatString = NSMutableAttributedString(string: "Bold", attributes: [NSAttributedString.Key.foregroundColor : UIColor.green,
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 16),
NSAttributedString.Key.backgroundColor : UIColor.lightGray,
NSAttributedString.Key.shadow : myShadow])
let normalString = NSAttributedString(string: "\n\nNormal", attributes: [NSAttributedString.Key.foregroundColor : UIColor.white,
NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)])
let italicString = NSAttributedString(string: "\n\nItalic", attributes: [NSAttributedString.Key.foregroundColor : UIColor.yellow,
NSAttributedString.Key.font : UIFont.italicSystemFont(ofSize: 16)])
let otherFontString = NSAttributedString(string: "\n\nBold + Italic", attributes: [NSAttributedString.Key.foregroundColor : UIColor.gray,
NSAttributedString.Key.font : UIFont(descriptor: UIFontDescriptor().withSymbolicTraits([.traitBold, .traitItalic])!, size: 16)])
let normalString2 = NSAttributedString(string: "\n\nUnderlined", attributes: [NSAttributedString.Key.underlineStyle : NSUnderlineStyle.single.rawValue,
NSAttributedString.Key.foregroundColor : UIColor.red,
NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)])
attributedText.append(fatString)
attributedText.append(normalString)
attributedText.append(italicString)
attributedText.append(otherFontString)
attributedText.append(normalString2)
textLabel.attributedText = attributedText
}
}

How to create random string with multiple formats?

I need to create a random string with format which can convert any string(including parenthesis() to another color on swift: for example:
Hey (Hey) : First part 'Hey' is fine, but I want to change : (Hey) to a different color
same goes if I choose another string
Hi (What's Up) ....
And tried the following
let label = UILabel(frame: CGRect(origin: .zero, size: CGSize(width: 200, height: 50)))
let color = UIColor(white: 0.2, alpha: 1)
let attributedTextCustom = NSMutableAttributedString(string: "(\(String())", attributes: [.font: UIFont(name:"AvenirNext-Medium", size: 16)!, .foregroundColor: color]))
attributedTextCustom.append(NSAttributedString(string: " (\(String())", attributes: [.font: UIFont(name: "AvenirNext-Regular", size: 12)!, .foregroundColor: UIColor.lightGray]))
label.attributedText = attributedTextCustom
Something like this is the behavior I am looking for (just for demostration...):
You can use a regex "\\((.*?)\\)" to find the range of the word between the parentheses and add the color attribute to a NSMutableAttributedString:
let label = UILabel(frame: CGRect(origin: .zero, size: CGSize(width: 200, height: 50)))
let sentence = "Hello (Playground)"
let mutableAttr = NSMutableAttributedString(string: sentence, attributes: [.font: UIFont(name:"AvenirNext-Medium", size: 16)!, .foregroundColor: UIColor.black])
if let range = sentence.range(of: "\\((.*?)\\)", options: .regularExpression) {
let color = UIColor(white: 0.2, alpha: 1)
let attributes: [NSAttributedString.Key: Any] = [.font: UIFont(name:"AvenirNext-Medium", size: 16)!, .foregroundColor: color]
mutableAttr.addAttributes(attributes, range: NSRange(range, in: sentence))
label.attributedText = mutableAttr
}

Add several attributes to a NSMutableAttributedString

I'm trying to add several attributes to a NSMutableAttributedString; i tried this:
let stringNumero: NSString = "\(squadra.cori.count)" //= two-digit number
var stringNumeroMutable = NSMutableAttributedString()
stringNumeroMutable = NSMutableAttributedString(string: stringNumero as! String, attributes: [NSFontAttributeName: UIFont(name: "Noteworthy-Light", size: 9)!,
NSForegroundColorAttributeName: UIColor(red: 110/255.0, green: 183/255.0, blue: 93/255.0, alpha: 1.0)])
cell.numeroCori.attributedText = stringNumeroMutable
now I'd like to add an other attributes and i'm going uso this code:
stringNumeroMutable.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(8), range: NSRange(location: 0, length: 1))
but I'm incurring in a problem:
as you see, the bold effect is attributed only to the first digit and the previous attributed (such as the font) disappear. I think the the second NSFontAttributedName subscribe the previous one, so is there any way to set both font and bold?
Thanks a lot!!!
Edit: as suggested i tried to recall the method like this:
let stringNumero: NSString = "\(squadra.cori.count)" //= two-digit number
var stringNumeroMutable = NSMutableAttributedString()
stringNumeroMutable = NSMutableAttributedString(string: stringNumero as! String, attributes: [NSFontAttributeName: UIFont(name: "Noteworthy-Light", size: 9)!,
NSForegroundColorAttributeName: UIColor(red: 110/255.0, green: 183/255.0, blue: 93/255.0, alpha: 1.0)])
cell.numeroCori.attributedText = stringNumeroMutable
stringNumeroMutable.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(9), range: NSRange(location: 0, length: stringNumeroMutable.length))
cell.numeroCori.atributedText = stringNumeroMutable
but the second call overwrite the first one (so the number loose the attributed font). How to solve this?
I think your problem, that you use method boldSystemFontOfSize
boldSystemFontOfSize:
Returns the font object used for standard interface items that are
rendered in boldface type in the specified size.
See my solution:
#IBOutlet weak var label: UILabel!
var mutableAttributedString: NSMutableAttributedString!
override func viewDidLoad() {
super.viewDidLoad()
let someString = "Hello World"
let attr: [String: AnyObject] = [NSFontAttributeName: UIFont(name: "Helvetica", size: 10)!,
NSForegroundColorAttributeName: UIColor(red: 0.18, green: 0.18, blue: 0.18, alpha: 1.0)]
mutableAttributedString = NSMutableAttributedString(string: someString, attributes: attr)
label.attributedText = mutableAttributedString
}
#IBAction func buttonPressed(sender: UIButton) {
let font = mutableAttributedString.attribute(NSFontAttributeName, atIndex: 1, effectiveRange: nil)!
mutableAttributedString.addAttribute(NSFontAttributeName, value: font.fontWithSize(20) , range: NSMakeRange(0, mutableAttributedString.length))
label.attributedText = mutableAttributedString
}
In buttonPressed function you define current font of mutableAttributedString and then you can change font's size with method fontWithSize.