NSAttributedString: how to make multiline in another NSAttributedString - ios

I am trying to create a multiline separate text in another text to achieve the below text style.
I have tried the below code to produce the goal but the third part of the code is creating a issue (with medium font)
private func createLimitedDetailText() -> NSAttributedString {
let totalText = "Attension, only\n 6 spaces\n left!"
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let attributedString = NSMutableAttributedString(string: totalText, attributes: [
.font: FontFamily.OpenSans.light.font(size: 29.0),
.foregroundColor: UIColor.white,
])
let bigText = attributedString.addAttribute(.font, value: FontFamily.OpenSans.extrabold.font(size: 70), range: NSRange(location: 17, length: 1))
let medium = attributedString.addAttribute(.font, value: FontFamily.OpenSans.semibold.font(size: 29), range: NSRange(location: 18, length: 14))
let textRange = NSRange(location: 0, length: attributedString.length)
attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: textRange)
return attributedString
}

In case anyone is wondering the answer, below code generates the exact same result:
private func createLimitedDetailText() -> NSAttributedString {
let totalText = "Attension, only\n 6"
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineHeightMultiple = 0.90
paragraphStyle.alignment = .center
let attributedString = NSMutableAttributedString(string: totalText, attributes: [
.font: FontFamily.OpenSans.light.font(size: 29.0),
.foregroundColor: UIColor.white,
NSAttributedString.Key.paragraphStyle: paragraphStyle
])
attributedString.addAttribute(.font, value: FontFamily.OpenSans.extrabold.font(size: 70), range: NSRange(location: 17, length: 1))
let paragraphStyle2 = NSMutableParagraphStyle()
paragraphStyle2.lineHeightMultiple = 0.30
paragraphStyle2.alignment = .center
let attributedString2 = NSMutableAttributedString(string: " spaces\n left!", attributes: [
.font: FontFamily.OpenSans.semibold.font(size: 29.0),
.foregroundColor: UIColor.white,
.baselineOffset: 35,
.paragraphStyle: paragraphStyle2
])
attributedString.append(attributedString2)
return attributedString
}

Related

line strikethrough is not show in middle of UILabel swift iOS

I have assigned attributedText to UILabel see the following code, But strike through line is not displayed center (vertically/meddle) of UIlabel text.
let strikethroughAttribute = [
.font: UIFont(name: "Roboto-Medium", size: 16.0)!,
.foregroundColor: UIColor.gray,
.strikethroughStyle: NSUnderlineStyle.single.rawValue,
.strikethroughColor: UIColor.gray] as [NSAttributedString.Key : Any]
}
var formattedString = NSMutableAttributedString(string: "$198")
formattedString.addAttributes(strikethroughAttribute, range: NSMakeRange(0, formattedString.length))
label.attributedText = formattedString

Wrong height for UILabel when using custom lineSpacing and kern

I am getting wrong height for an UILabel if I use NSAttributedString that has custom kern and lineSpacing.
Here is how I set the custom kern and line spacing:
override func viewDidLoad() {
super.viewDidLoad()
let shortText = "Single line"
self.label.attributedText = self.getAttributedText(text: shortText, kern: 0.2, lineSpacing: 8)
self.label2.attributedText = self.getAttributedText(text: shortText, kern: 0, lineSpacing: 8)
}
private func getAttributedText(text: String, kern: CGFloat, lineSpacing: CGFloat) -> NSAttributedString {
let attributedString = NSMutableAttributedString(string: text)
let style = NSMutableParagraphStyle()
style.lineSpacing = lineSpacing
let attributes: [NSAttributedStringKey : Any] =
[.paragraphStyle : style,
.kern: kern]
attributedString.addAttributes(attributes,
range: NSMakeRange(0, attributedString.length))
return attributedString
}
And here is what I get:
The first label (the one that has custom kern), has its height wrong. It's exactly 8 points taller than it should be - that's the custom line height that I am using.
This only happens for single line labels. If I use text that is on a couple of lines, it works as expected.
This is a bug with NSAttributedStringKey.kern. As a workaround, you can calculate the number of lines of your UILabel with the suggestions in this answer. If it has one line only, set lineSpacing to 0.
private func getAttributedText(text: String, kern: CGFloat, lineSpacing: CGFloat) -> NSAttributedString {
let attributedString = NSMutableAttributedString(string: text)
let font = UIFont.systemFont(ofSize: 16)
let attributes: [NSAttributedStringKey : Any] = [.kern: kern,
.font: font]
attributedString.addAttributes(attributes, range: NSMakeRange(0, attributedString.length))
let maxSize = CGSize(width: [custom width], height: CGFloat.greatestFiniteMagnitude)
let sizeOfLabel = attributedString.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil)
if sizeOfLabel.height > font.lineHeight {
let style = NSMutableParagraphStyle()
style.lineSpacing = lineSpacing
attributedString.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, attributedString.length))
}
return attributedString
}

Adding font size and custom font name to attributed string in UITextView

I have the following code to add the attributed string to the UITextView text. I need to add the custom font and font size to it in swift. How to do it?
func setAttributedString(string: String) -> NSAttributedString {
let attrString = NSMutableAttributedString(string: string)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 7
paragraphStyle.minimumLineHeight = 7
attrString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:NSRange(location: 0, length:attrString.length))
attrString.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: 30), range: NSRange(location: 0, length:attrString.length))
return attrString
}
I need to add the custom font and font size to the following function. How to achieve this?
In Swift 3
let attributes = [NSAttributedStringKey.font: UIFont(name: "HelveticaNeue-Bold", size: 17)!,
NSAttributedStringKey.foregroundColor: UIColor.white]
let attributedString = NSMutableAttributedString(string: "Your string" , attributes: attributes)
Use the initializer init(string:attributes:)
https://developer.apple.com/documentation/foundation/nsattributedstring/1408136-init
let attrString = NSMutableAttributedString(string: string, attributes:
[NSFontAttributeName:UIFont(
name: "Georgia",
size: 18.0)!])
//Add more attributes here

UITextContainerView hidding clickable link of UITextView

I made a clickable link in a UITextView using NSMutableAttributeString.
All it changes is that the text is highlighted
As we can see : floating over my UITextView there is a UIContainerView (I really don't know if its because of that.. I'm trying)
Here is my UIView code:
class InfoBox: UIView {
let Heading: UITextView = {
let textView = UITextView(frame: CGRect(x: 15, y: 0, width: 200, height: 35))
textView.font = UIFont.systemFont(ofSize: 20)
textView.textColor = UIColor.white
textView.isScrollEnabled = false
textView.backgroundColor = UIColor.clear
textView.isEditable = false
textView.isSelectable = true
return textView
}()
let TextContent: UITextView = {
let textView = UITextView(frame: CGRect(x: 15, y: 27, width: UIScreen.main.bounds.width, height: 30))
textView.font = UIFont.systemFont(ofSize: 17)
textView.textColor = UIColor.white
textView.isScrollEnabled = false
textView.backgroundColor = UIColor.clear
textView.isEditable = false
textView.isSelectable = true
return textView
}()}
The NSAttributedString code:
func transformText(text: String, underlined: Bool, linkURL: String) -> NSAttributedString {
let textRange = NSMakeRange(0, text.characters.count)
let attributedText = NSMutableAttributedString(string: text)
if underlined{
attributedText.addAttribute(NSUnderlineStyleAttributeName , value: NSUnderlineStyle.styleSingle.rawValue, range: textRange)
attributedText.addAttribute(NSUnderlineColorAttributeName , value: UIColor.lightGray, range: textRange)
}
attributedText.addAttribute(NSFontAttributeName , value: UIFont(name: "Helvetica-Light", size: 17)!, range: textRange)
attributedText.addAttribute(NSForegroundColorAttributeName , value: UIColor.lightGray, range: textRange)
if(linkURL != "")
{
let attrib = [NSLinkAttributeName: NSURL(string: linkURL)!]
attributedText.addAttributes(attrib, range: textRange)
}
return attributedText
}
And this is how it is called:
self.TelBox.TextContent.attributedText = transformText(text: self.TelBox.TextContent.text, underlined: true, linkURL: "https://www.google.fr")
Secondary question : is it possible to make a clickable link in a UITextView for a telephone number so that when clicked it calls that number? Did it with a UIButton .
I am not sure what is wrong with your UIContainerView, as far as i can see there's nothing wrong there.
Here's the method to make the link call a number:
func transformText(text: String, underlined: Bool, phoneNumber: String) -> NSAttributedString {
let textRange = NSMakeRange(0, text.characters.count)
let attributedText = NSMutableAttributedString(string: text)
if underlined{
attributedText.addAttribute(NSAttributedStringKey.underlineStyle , value: NSUnderlineStyle.styleSingle.rawValue, range: textRange)
attributedText.addAttribute(NSAttributedStringKey.underlineColor , value: UIColor.lightGray, range: textRange)
}
attributedText.addAttribute(NSAttributedStringKey.font , value: UIFont(name: "Helvetica-Light", size: 17)!, range: textRange)
attributedText.addAttribute(NSAttributedStringKey.foregroundColor , value: UIColor.lightGray, range: textRange)
if(phoneNumber != "")
{
let attrib = [
NSAttributedStringKey.link: URL(string: "tel://" + phoneNumber.replacingOccurrences(of: " ", with: ""))]
attributedText.addAttributes(attrib, range: textRange)
}
return attributedText
}
You can use it like this: TextContent.attributedText = transformText(text: "12345", underlined: true, phoneNumber: "12345")

ios swift: Is it possible to change the font style of a certain word in a string?

I am extracting from a DB contents as strings. With a method I extract the longest word out of this string.
Now I would like to print out the entire string to a text label but would like to highlight the longest word in a different color and text style within the string.
How can I do that?
Do I need to cut the string into pieces - set the formatting - and put them all together again before giving it to the label?
Or is there any other (better) way?
If you already know the longest word you have to get the range of that word in the string. I prefer the NSString method rangeOfString: for this.
You then create a NSMutableAttributedString from the string, with your default attributes. Finally you apply highlighting attributes to the range you figured out earlier.
let longString = "Lorem ipsum dolor. VeryLongWord ipsum foobar"
let longestWord = "VeryLongWord"
let longestWordRange = (longString as NSString).rangeOfString(longestWord)
let attributedString = NSMutableAttributedString(string: longString, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(20)])
attributedString.setAttributes([NSFontAttributeName : UIFont.boldSystemFontOfSize(20), NSForegroundColorAttributeName : UIColor.redColor()], range: longestWordRange)
label.attributedText = attributedString
Update for Swift 5.0
let longestWordRange = (longString as NSString).range(of: longestWord)
let attributedString = NSMutableAttributedString(string: longString, attributes: [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 20)])
attributedString.setAttributes([NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 20), NSAttributedStringKey.foregroundColor : UIColor.red], range: longestWordRange)
Which looks like this in my playground:
You want to look at Attributed Strings and NSRange. You can use both of these together to create different styles for ranges in the string. Here is a snippet:
myMutableString = NSMutableAttributedString(string: myString, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 18.0)!])
//Add more attributes here:
myMutableString.addAttribute(NSFontAttributeName, value: UIFont(name: "Chalkduster", size: 24.0), range: NSRange(location: 7,length: 5))
myMutableString.addAttribute(NSFontAttributeName, value: UIFont(name: "AmericanTypewriter-Bold", size: 18.0)!, range: NSRange(location:2,length:4))
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: NSRange(location:2,length:4))
myMutableString.addAttribute(NSFontAttributeName, value: UIFont(name: "Georgia", size: 36.0)!, range: NSRange(location: 0, length: 1))
myMutableString.addAttribute(NSStrokeColorAttributeName, value: UIColor.blueColor(), range: NSRange(location: 0, length: 1))
myMutableString.addAttribute(NSStrokeWidthAttributeName, value: 2, range: NSRange(location: 0, length: 1))
myMutableString.addAttribute(NSBackgroundColorAttributeName, value: UIColor.greenColor(), range: NSRange(location: 0, length: myString.length))
myLabel.backgroundColor = UIColor.grayColor()
//Apply to the label
myLabel.attributedText = myMutableString
NSMutableAttributedString.
You create an NSMutableAttributedString and apply the effects you'd like with addAttributes:range.
Then assign it to the attributedText property of your UILabel.

Resources