Objective c - Multiple colors in a label - ios

What is the easiest way to have a label with different colors?
For example I want to present the message:
"John Johnson sent you a message"
But I want that John Johnson will be in blue color
and the rest of the message in black color.

You need the NSAttributedString class (or the mutable one - NSMutableAttributedString) in order to set attributes (for example, font and kerning) that apply to individual characters or ranges of characters in the string and a custom label control that can visualize NSAttributedString like TTTAttributedLabel.

In UILabel basically impossible. If you want to this you must override drawTextInRect should be executed. But I will recommend OHAttributedLabel. this is have a attributedString is a textcolor can be set to specify a range.

Use a UIWebView.
webView.text =
#"<span style:\"color:blue;\">John Johnson</span> sent you a message.";

Use CoreText. Hope this helps.

I created an UILabel extension to do this. Basically what it does is use NSAttributedString to define the color for some particular range: https://github.com/joaoffcosta/UILabel-FormattedText
If you wish to implement this behavior yourself, just do the following:
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithAttributedString: #"John Johnson sent you a message"];
[text addAttribute: NSFontAttributeName
value: font
range: range];
[self setAttributedText: text];

Try this with swift (execute code with following extension)
extension NSMutableAttributedString {
func setColorForText(textToFind: String, withColor color: UIColor) {
let range: NSRange = self.mutableString.range(of: textToFind, options: .caseInsensitive)
self.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
}
}
Try an extension with UILabel:
let label = UILabel()
label.frame = CGRect(x: 40, y: 100, width: 280, height: 200)
let stringValue = "John Johnson sent you a message" // or direct assign single string value like "firstsecondthird"
label.textColor = UIColor.lightGray
label.numberOfLines = 0
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: stringValue)
attributedString.setColorForText(textToFind: "John Johnson", withColor: UIColor.blue)
label.font = UIFont.systemFont(ofSize: 26)
label.attributedText = attributedString
self.view.addSubview(label)
Here is result:

Related

Give UITextView a clickable URL link

Hi I've been on this problem for a while now, I read a couple of posts already an I can't understand how to make a clickable UITextView that sends on internet. Here is my 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
}
Here is how i call it:
TextContent.attributedText = transformText(text: self.TelBox.TextContent.text, underlined: true, linkURL: "https://www.google.fr")`
Thanks in advance
Select the UITextView on storyboard and go to 'Show the Attributes inspector', then in 'behavior' unselects 'Editable' and in 'Data Detector' select 'Link'. Then go to 'Sohw the Identity inspector' and in 'traits' select 'Link' and 'Selected'.
You must set editable YES or set selectable YES
NSString *text = #"this is google web link";
UITextView *textView = [[UITextView alloc] init];
NSDictionary *dictionary = #{NSFontAttributeName:[UIFont systemFontOfSize:10],NSForegroundColorAttributeName:[UIColor whiteColor]};
NSMutableAttributedString *attributeStr = [[NSMutableAttributedString alloc] initWithString:text attributes:dictionary];
textView.attributedText = attributeStr;
[attributeStr addAttributes:#{NSLinkAttributeName: [NSURL URLWithString:#"http://www.google.com"]} range:[_readMessage rangeOfString:#"google web link"]];
textView.attributedText = attributeStr;
textView.editable = NO;
textView.selectable = YES;
textView.delegate = self;
google link will reponse by delegate
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
The fact is you want to make UITextView to make clickable requires you to make UITextView non editable because when you click on text it will lunch keyboard. To prevent this you can use
textView.isEditable = false
Hope it helps.
Make sure you've also enabled data type detection. For hyperlinks:
theTextView.dataDetectorTypes = [.link]

How to add spacing to lines in NSAttributedString

I am making an app that formats screenplays, I am using a NSAttributedString to format the text entered into a UITextView, but some of the lines are too close together.
I was wondering if anyone could provide a code example or a tip on how to alter the margin between these lines so there is more space between them.
Below is an image of another desktop screenwriting program that demonstrates what I mean, notice how there is a bit of space before each bit where it says "DOROTHY".
The following sample code uses paragraph style to adjust spacing between paragraphs of a text.
UIFont *font = [UIFont fontWithName:fontName size:fontSize];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.paragraphSpacing = 0.25 * font.lineHeight;
NSDictionary *attributes = #{NSFontAttributeName:font,
NSForegroundColorAttributeName:[UIColor whiteColor],
NSBackgroundColorAttributeName:[UIColor clearColor],
NSParagraphStyleAttributeName:paragraphStyle,
};
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text attributes:attributes];
To selectively adjust spacing for certain paragraphs, apply the paragraph style to only those paragraphs.
Hope this helps.
Great answer #Joe Smith
In case anyone would like to see what this looks like in Swift 2.*:
let font = UIFont(name: String, size: CGFloat)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.paragraphSpacing = 0.25 * font.lineHeight
let attributes = [NSFontAttributeName:font, NSParagraphStyleAttributeName:paragraphStyle]
let attributedText = NSAttributedString(string: String, attributes: attributes)
self.textView.attributedText = attributedText
Here is Swift 4.* version:
let string =
"""
A multiline
string here
"""
let font = UIFont(name: "Avenir-Roman", size: 17.0)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.paragraphSpacing = 0.25 * (font?.lineHeight)!
let attributes = [NSAttributedStringKey.font: font as Any, NSAttributedStringKey.paragraphStyle: paragraphStyle]
let attrText = NSAttributedString(string: string, attributes: attributes)
self.textView.attributedText = attrText

How to set a space between characters and lines in UILabel

I'd like set one spacing between first and second lines, between other lines need another spacing. With this, second and next lines must have specific character spacing.
This all need doing in one control. How i can do this? I decided to create a separate UILabel for each row but i think it's wrong way.
You can't change the spacing between lines of text, you will have to subclass UILabel and roll your own drawTextInRect, create multiple labels, or use a different font.
But there are two custom Labels, that allow you to control the lineheight.
1) https://github.com/LemonCake/MSLabel
2) https://github.com/Tuszy/MTLabel
Hope this helps...
In iOS6, you could do this:
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:40];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
cell.label.attributedText = attributedString ;
Try this, it should work for you (with Swift 4)
let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
// add strike
attrString.addAttribute(NSAttributedStringKey.strikethroughStyle, value: 2, range: NSMakeRange(0, attrString.length))
// add space between characters
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))
label.attributedText = attrString
Result:

Two colors for UILabel TEXT

I want to set two colors for UILabel's text. I tried TTTRegexAttributedLabel, but it is throwing unknown type error.
I tried following code too. But it is crashing at settext.
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:#"Hello. That is a test attributed string."];
[str addAttribute: #"Hello" value:[UIColor yellowColor] range:NSMakeRange(3,5)];
[str addAttribute:#"That" value:[UIColor greenColor] range:NSMakeRange(10,7)];
[str addAttribute:#"Hello" value:[UIFont fontWithName:#"HelveticaNeue-Bold" size:20.0] range:NSMakeRange(20, 10)];
[syncStatusLabel setText:(NSString *)str];
Is there any other way to set multiple colors for single UILabel text?
you can set text color with pattern image like bellow..
[yourLable setTextColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"yourImageName"]]];
and also set different color with this bellow code.. please check tutorial with detail mate..
NSString *test = #"Hello. That is a test attributed string.";
CFStringRef string = (CFStringRef) test;
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (attrString,CFRangeMake(0, 0), string);
/*
Note: we could have created CFAttributedStringRef which is non mutable, then we would have to give all its
attributes right when we create it. We can change them if we use mutable form of CFAttributeString.
*/
//Lets choose the colors we want to have in our string
CGColorRef _orange=[UIColor orangeColor].CGColor;
CGColorRef _green=[UIColor greenColor].CGColor;
CGColorRef _red=[UIColor redColor].CGColor;
CGColorRef _blue=[UIColor blueColor].CGColor;
//Lets have our string with first 20 letters as orange
//next 20 letters as green
//next 20 as red
//last remaining as blue
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 20),kCTForegroundColorAttributeName, _orange);
CFAttributedStringSetAttribute(attrString, CFRangeMake(20, 20),kCTForegroundColorAttributeName, _green);
CFAttributedStringSetAttribute(attrString, CFRangeMake(40, 20),kCTForegroundColorAttributeName, _red);
CFAttributedStringSetAttribute(attrString, CFRangeMake(60, _stringLength-61),kCTForegroundColorAttributeName, _blue);
for more information see this tutorial....
coretext-tutorial-for-ios-part
i hope this help you...
NSAttributedString has to be set using UILabel's attributedText property. e.g [syncStatusLabel setAttributedText:str] in your case. Good Luck!
Try this with swift (execute code with following extension)
extension NSMutableAttributedString {
func setColorForText(textToFind: String, withColor color: UIColor) {
let range: NSRange = self.mutableString.range(of: textToFind, options: .caseInsensitive)
self.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
}
}
Try an extension with UILabel:
self.view.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
let label = UILabel()
label.frame = CGRect(x: 40, y: 100, width: 280, height: 200)
let stringValue = "Hello. That is a test attributed string." // or direct assign single string value like "firstsecondthird"
label.textColor = UIColor.lightGray
label.numberOfLines = 0
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: stringValue)
attributedString.setColorForText(textToFind: "Hello", withColor: UIColor.yellow)
attributedString.setColorForText(textToFind: "That", withColor: UIColor.green)
label.font = UIFont.systemFont(ofSize: 26)
label.attributedText = attributedString
self.view.addSubview(label)
Here is result:

Set UILabel line spacing

How can I modify the gap between lines (line spacing) in a multiline UILabel?
Edit: Evidently NSAttributedString will do it, on iOS 6 and later. Instead of using an NSString to set the label's text, create an NSAttributedString, set attributes on it, then set it as the .attributedText on the label. The code you want will be something like this:
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:#"Sample text"];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:24];
[attrString addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, strLength)];
uiLabel.attributedText = attrString;
NSAttributedString's old attributedStringWithString did the same thing, but now that is being deprecated.
For historical reasons, here's my original answer:
Short answer: you can't. To change the spacing between lines of text, you will have to subclass UILabel and roll your own drawTextInRect, create multiple labels, or use a different font (perhaps one edited for a specific line height, see Phillipe's answer).
Long answer: In the print and online world, the space between lines of text is known as "leading" (rhymes with 'heading', and comes from the lead metal used decades ago). Leading is a read-only property of UIFont, which was deprecated in 4.0 and replaced by lineHeight. As far as I know, there's no way to create a font with a specific set of parameters such as lineHeight; you get the system fonts and any custom font you add, but can't tweak them once installed.
There is no spacing parameter in UILabel, either.
I'm not particularly happy with UILabel's behavior as is, so I suggest writing your own subclass or using a 3rd-party library. That will make the behavior independent of your font choice and be the most reusable solution.
I wish there was more flexibility in UILabel, and I'd be happy to be proven wrong!
Starting in ios 6 you can set an attributed string in the UILabel:
NSString *labelText = #"some text";
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineSpacing:40];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
cell.label.attributedText = attributedString ;
You can control line spacing in the storyboard:
duplicate question
From Interface Builder:
Programmatically:
SWift 4
Using label extension
extension UILabel {
func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
guard let labelText = self.text else { return }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.lineHeightMultiple = lineHeightMultiple
let attributedString:NSMutableAttributedString
if let labelattributedText = self.attributedText {
attributedString = NSMutableAttributedString(attributedString: labelattributedText)
} else {
attributedString = NSMutableAttributedString(string: labelText)
}
// Line spacing attribute
attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}
Now call extension function
let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) . // try values 1.0 to 5.0
// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0
Or using label instance (Just copy & execute this code to see result)
let label = UILabel()
let stringValue = "Set\nUILabel\nline\nspacing"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))
label.attributedText = attrString
Swift 3
let label = UILabel()
let stringValue = "Set\nUILabel\nline\nspacing"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
attrString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
label.attributedText = attrString
My solution was to patch the font file itself and fix its line height definitely.
http://mbauman.net/geek/2009/03/15/minor-truetype-font-editing-on-a-mac/
I had to modify 'lineGap', 'ascender', 'descender' in the 'hhea' block (as in the blog example).
This guy created a class to get line-height (without using CoreText, as MTLabel library) : https://github.com/LemonCake/MSLabel
Best thing I found is: https://github.com/mattt/TTTAttributedLabel
It's a UILabel subclass so you can just drop it in, and then to change the line height:
myLabel.lineHeightMultiple = 0.85;
myLabel.leading = 2;
I've found 3rd Party Libraries Like this one:
https://github.com/Tuszy/MTLabel
To be the easiest solution.
Here's some swift-code for you to set the line spacing programmatically
let label = UILabel()
let attributedText = NSMutableAttributedString(string: "Your string")
let paragraphStyle = NSMutableParagraphStyle()
//SET THIS:
paragraphStyle.lineSpacing = 4
//OR SET THIS:
paragraphStyle.lineHeightMultiple = 4
//Or set both :)
let range = NSMakeRange(0, attributedText.length)
attributedText.addAttributes([NSParagraphStyleAttributeName : paragraphStyle], range: range)
label.attributedText = attributedText
Of course, Mike's answer doesn't work if you pass the string programmatically. In this case you need to pass a attributed string and change it's style.
NSMutableAttributedString * attrString = [[NSMutableAttributedString alloc] initWithString:#"Your \nregular \nstring"];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:4];
[attrString addAttribute:NSParagraphStyleAttributeName
value:style
range:NSMakeRange(0, attrString.length)];
_label.attributedText = attrString;

Resources