I wanted to change the text of a label that says "hello world" such that "hello" is red, and "world" is blue. I'm doing this programmatically and obviously simplifying this example.
Is there a way to do this?
My alternative was to just create two uilabels, and set the attributes of each one accordingly, and then just add them together next to each other, but I thought it would be great if I could just assign the text of a label as per above instead.
By the way it doesn't have to be a UILabel as long as I can just render this text inside a UITableView row.
Thanks!
Here is a small example on how to use NSAttributedString:
var resultString = NSMutableAttributedString(string: "Hello ", attributes: [NSForegroundColorAttributeName : UIColor.redColor()])
var worldString = NSMutableAttributedString(
string: "World",
attributes: [
NSForegroundColorAttributeName : UIColor.redColor(),
NSFontAttributeName : UIFont.boldSystemFontOfSize(13.0)
]
)
resultString.appendAttributedString(worldString)
Then you can assign it to UILabel:
UILabel().attributedText = resultString
Related
As you can see from the image, the background of the UILabel is set to yellow. The attributed text does not use all the space before wrapping to the next line ("at" should be in the first line). Any way to fix it?
The label is constructed as follows. It is inside a UICollectionView header, and positioned by autolayout
let astring = NSMutableAttributedString(string: "You asked friends, and people at ")
astring.append(NSAttributedString(string:"Pittsburgh",
attributes: [.font: UIFont.boldSystemFont(ofSize: 15)]))
let label = UILabel()
label.attributedText = astring
Yes, odd bug...
One work-around, although I haven't done any testing on it except to see that it works in your case.
Append a "no-width space" character at the end:
let astring = NSMutableAttributedString(string: "You asked friends, and people at ")
astring.append(NSAttributedString(string:"Pittsburgh",
attributes: [.font: UIFont.boldSystemFont(ofSize: 15)]))
astring.append(NSAttributedString(string:"\u{200b}",
attributes: [.font: UIFont.systemFont(ofSize: 15)]))
Result:
Append the ""\u{200b}" in Attributed String in End . hope it it will work ,
This is the string I use:
CASE 1
var word1 = "عبد الله"
var word2 = "restaurant"
label.text = " \(word1) found your review on \(word2) useful."
Result:
CASE 2
var word1 = "عبد الله"
var word2 = "restaurant"
label.text = "note: \(word1) found your review on \(word2) useful."
Result:
Question
so, how do I make the first word to wrap right? if the first word is arabic, it gets wrapped to the left, but if the first word is english the situation is expected, so how make the word1 to show up when first word on the left?
I tried both
label.textAlignment = NSTextAlignment.Left
and
label.textAlignment = NSTextAlignment.Natural
without any luck.
Unicode has two marker characters (LTR: 0x200E, RTL:200F). These are invisible, but control the direction, I just need to add this \u{200E} to force the wrapping direction.
\u{200E} \(word1) found your review on \(word2) useful.
EDIT:
see full tutorial here, for more info.
UILabel as a subclass of UIView has a variable named semanticContentAttribute which you can set to .foreRightToLeft, it can also be set from the nib inspector through the Semantic pop-up menu in the attributes inspector.
Moreover, you can query effectiveUserInterfaceLayoutDirection property for debugging it's state.
See this for reference.
Now if you need both alignments in one label it will be tricky, either group two labels in a container UIView or see if you can set these values for portions of an NSMutableAttributedString which you can feed to a UILabel.
The textAlignment properties you are trying to set will give you the same effect that MS-Word does to paragraph alignment but wouldn't flip reading direction for language.
Happy coding!
Edit: This is an example of what I am suggesting with attributed strings although when changing the arabic setting to RightToLeft it puts it at the bottom of the string... Maybe the flags need to be combined differently?
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel()
let myMutableString = NSMutableAttributedString()
//right-to-left
let multipleAttributes: [String : AnyObject] = [
NSForegroundColorAttributeName: UIColor.orangeColor(),
NSBackgroundColorAttributeName: UIColor.blueColor(),
NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleDouble.rawValue,
NSWritingDirectionAttributeName : [NSWritingDirection.LeftToRight.rawValue ]
]
let myAttrString = NSAttributedString(string: "عبد الله", attributes: multipleAttributes)
myMutableString.appendAttributedString(myAttrString)
//some-text
let someText = NSAttributedString(string: " finds ", attributes: nil)
myMutableString.appendAttributedString(someText)
//left-to-right
let multipleAttributes2: [String : AnyObject] = [
NSForegroundColorAttributeName: UIColor.blueColor(),
NSBackgroundColorAttributeName: UIColor.yellowColor(),
NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleDouble.rawValue,
NSWritingDirectionAttributeName : [NSWritingDirection.LeftToRight.rawValue | NSTextWritingDirection.Embedding.rawValue]
]
let myAttrString2 = NSAttributedString(string: "restaurant", attributes: multipleAttributes2)
myMutableString.appendAttributedString(myAttrString2)
label.attributedText = myMutableString
self.view.addSubview(label)
label.sizeToFit()
label.center = self.view.center
}
I'm using
titleLabel.Lines = 2;
titleLabel.LineBreakMode = UILineBreakMode.TailTruncation;
Now long text is broken by a ... in the end.
Now I would like to know if the titleLabel is tail truncated , contains "..." ? Any easy suggestions for this ?? as I cannot see the ... characters in the actual titleLabel.Text field
Your question is similar to Change the default '...' at the end of a text if the content of a UILabel doesn't fit
There is no direct option to access ellipsis(the three dot). You need to do it yourself. Code to count the size of your string, clip the string and add a ellipsis with the color you want when the string exceed the view.
Define a NSAttributesString
let atttext = NSAttributedString(string: text!, attributes: [NSForegroundColorAttributeName: UIColor.redColor()])
Calculate the size of the string
let bounds = atttext.boundingRectWithSize(label.bounds.size, options: [], context: nil)
Do something to the string when it exceed the view
if bounds.size.width > 10 {
//Do something here, like assign a new value to `attributedText` of label or change the color
label.attributedText = NSAttributedString(string: "Labelfdjkfdsjkfdsjkf...", attributes: [NSForegroundColorAttributeName: UIColor.blackColor()])
}
For more detail, you can have a look at the last answer of the question I mentioned above.
I just couldn't find utf-8 encoding for character like following:
I think that it is quite possible to create this in code, as a composed character from two dashes: / and \, but I do not know what characters to compose.
Maybe U+003C
print("\u{003C}") // <
Possibly U+2039.
print("\u{2039}") // ‹
Or U+276E.
print("\u{276E}") // ❮
I'm not certain if this will work for a navigation item, but you could make use of NSAttributedString to have string with different sizes of the substrings within it. This is described in detail in this great answer:
How do I make an attributed string using Swift?
As an example for your case:
let myAttributeBack = [ NSFontAttributeName: UIFont(name: "HelveticaNeue-UltraLight", size: 30.0)!]
let attrString = NSMutableAttributedString(string: "\u{276E} ", attributes: myAttributeBack)
let myAttributeText = [ NSFontAttributeName: UIFont(name: "HelveticaNeue-UltraLight", size: 15.0)!]
let backString = NSAttributedString(string: "back", attributes: myAttributeText)
attrString.appendAttributedString(backString)
myLabel.attributedText = attrString
However, as you write below, perhaps it's not possible to use attributed strings for title of a navigation bar item. Then I'd assume that the navigation bar example you showed above simply contains an image with the back bracket and a string "back" for the title text.
Is it this:
〈
The code is U+276C.
see https://en.wiktionary.org/wiki/%E3%80%88
I have a UILabel in my storyboard, and I have an #IBOutlet to it in my controller. In my viewDidLoad, I am setting its attributed text with two different font sizes.
let str1 = NSMutableAttributedString(string: "first", attributes: [NSFontAttributeName: UIFont.systemFontOfSize(15.0)])
let str2 = NSMutableAttributedString(string: "second", attributes: [NSFontAttributeName: UIFont.systemFontOfSize(10.0)])
str1.appendAttributedString(str2)
myLabel.attributedText = str1
Unfortunately, when I run the app, I can see the "firstsecond" string, but all in the same size (str1's 15-point font). Why is str2's 10-point font not being set?
Thanks in advance.
You have to use addAttribute(...) to apply multiple attributes to the same string.
let first = "first"
let second = "second"
let string = NSMutableAttributedString(string: first + second)
string.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(15), range: NSMakeRange(0, first.characters.count))
string.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(10), range: NSMakeRange(first.characters.count, second.characters.count))
myLabel.attributedText = string
The documentation for UILabel's attributedText property states:
assigning a new value updates the values in the font, textColor, and
other style-related properties so that they reflect the style
information starting at location 0 in the attributed string.
So whatever the style information is at location 0, that's what the label's going to be. That's why you're only seeing str1's 15 point font.