117

I want to display a string like this in a UILabel:

There are 5 results.

Where the number 5 is red in color and the rest of the string is black.

How can I do this in code?

Krunal
  • 77,632
  • 48
  • 245
  • 261
Peter
  • 1,171
  • 2
  • 8
  • 4
  • 6
    @EmptyStack This is certainly **not** the case since iOS 4 supports NSAttributedString. See my answer below. –  Jun 28 '11 at 09:51

20 Answers20

224

The way to do it is to use NSAttributedString like this:

NSMutableAttributedString *text = 
 [[NSMutableAttributedString alloc] 
   initWithAttributedString: label.attributedText];

[text addAttribute:NSForegroundColorAttributeName 
             value:[UIColor redColor] 
             range:NSMakeRange(10, 1)];
[label setAttributedText: text];

I created a UILabel extension to do it.

Alex Cio
  • 6,014
  • 5
  • 44
  • 74
João Costa
  • 2,355
  • 1
  • 14
  • 7
72

I have done this by creating a category for NSMutableAttributedString

-(void)setColorForText:(NSString*) textToFind withColor:(UIColor*) color
{
    NSRange range = [self.mutableString rangeOfString:textToFind options:NSCaseInsensitiveSearch];

    if (range.location != NSNotFound) {
        [self addAttribute:NSForegroundColorAttributeName value:color range:range];
    }
}

Use it like

- (void) setColoredLabel
{
    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"Here is a red blue and green text"];
    [string setColorForText:@"red" withColor:[UIColor redColor]];
    [string setColorForText:@"blue" withColor:[UIColor blueColor]];
    [string setColorForText:@"green" withColor:[UIColor greenColor]];
    mylabel.attributedText = string;
}

SWIFT 3

extension NSMutableAttributedString{
    func setColorForText(_ textToFind: String, with color: UIColor) {
        let range = self.mutableString.range(of: textToFind, options: .caseInsensitive)
        if range.location != NSNotFound {
            addAttribute(NSForegroundColorAttributeName, value: color, range: range)
        }
    }
}

USAGE

func setColoredLabel() {
    let string = NSMutableAttributedString(string: "Here is a red blue and green text")
    string.setColorForText("red", with: #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1))
    string.setColorForText("blue", with: #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1))
    string.setColorForText("green", with: #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1))
    mylabel.attributedText = string
}

SWIFT 4 @kj13 Thanks for notifying

// If no text is send, then the style will be applied to full text
func setColorForText(_ textToFind: String?, with color: UIColor) {

    let range:NSRange?
    if let text = textToFind{
        range = self.mutableString.range(of: text, options: .caseInsensitive)
    }else{
        range = NSMakeRange(0, self.length)
    }
    if range!.location != NSNotFound {
        addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range!)
    }
}

I have did more experiments with attributes and below are the results, here is the SOURCECODE

Here is the result

Styles

anoop4real
  • 7,598
  • 4
  • 53
  • 56
  • 2
    You need to create a new Category for NSMutableAttributedString with the method...anyways I added this sample to github, you can grab and check it https://github.com/anoop4real/NSMutableAttributedString-Color – anoop4real Dec 22 '15 at 16:46
  • But i need to set the color of all alphabet with incasesensitive in a string ....like all "e" in red color of the whole string – Ravi Ojha Dec 23 '15 at 03:29
  • No visible @interface for 'NSMutableAttributedString' declares the selector 'setColorForText:withColor:' – ekashking Apr 01 '18 at 17:59
  • 1
    I got error 'Use of unresolved identifier 'NSForegroundColorAttributeName' with Swift4.1, but I replace 'NSForegroundColorAttributeName' to 'NSAttributedStringKey.foregroundColor' and building correctly. – kj13 May 29 '18 at 04:02
  • 1
    @kj13 Thanks for notifying, I updated the answer and added a few more styles – anoop4real May 30 '18 at 07:00
  • Swift 4.2: `addAttribute(NSAttributedString.Key.underlineStyle, value:NSUnderlineStyle.thick.rawValue, range: range!)` BTW, this control is brilliant! – ICL1901 Feb 14 '19 at 20:08
26

Here you go

NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:lblTemp.text];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,5)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(5,6)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(11,5)];
lblTemp.attributedText = string;
Hardik Mamtora
  • 1,642
  • 17
  • 23
21

Swift 4

// An attributed string extension to achieve colors on text.
extension NSMutableAttributedString {

    func setColor(color: UIColor, forText stringValue: String) {
       let range: NSRange = self.mutableString.range(of: stringValue, options: .caseInsensitive)
       self.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
    }

}

// Try it with label
let label = UILabel()
label.frame = CGRect(x: 70, y: 100, width: 260, height: 30)
let stringValue = "There are 5 results."
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: stringValue)
attributedString.setColor(color: UIColor.red, forText: "5")
label.font = UIFont.systemFont(ofSize: 26)
label.attributedText = attributedString
self.view.addSubview(label)

Result

enter image description here


Swift 3

func setColoredLabel() {
        var string: NSMutableAttributedString = NSMutableAttributedString(string: "redgreenblue")
        string.setColor(color: UIColor.redColor(), forText: "red")
        string.setColor(color: UIColor.greenColor(), forText: "green")
        string.setColor(color: UIColor.blueColor(, forText: "blue")
        mylabel.attributedText = string
    }


func setColor(color: UIColor, forText stringValue: String) {
        var range: NSRange = self.mutableString.rangeOfString(stringValue, options: NSCaseInsensitiveSearch)
        if range != nil {
            self.addAttribute(NSForegroundColorAttributeName, value: color, range: range)
        }
    }

Result:

enter image description here

Krunal
  • 77,632
  • 48
  • 245
  • 261
13
//NSString *myString = @"I have to replace text 'Dr Andrew Murphy, John Smith' ";
NSString *myString = @"Not a member?signin";

//Create mutable string from original one
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:myString];

//Fing range of the string you want to change colour
//If you need to change colour in more that one place just repeat it
NSRange range = [myString rangeOfString:@"signin"];
[attString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:(63/255.0) green:(163/255.0) blue:(158/255.0) alpha:1.0] range:range];

//Add it to the label - notice its not text property but it's attributeText
_label.attributedText = attString;
tomahh
  • 13,441
  • 3
  • 49
  • 70
raju dontiboina
  • 131
  • 1
  • 4
7

Since iOS 6, UIKit supports drawing attributed strings, so no extension or replacement is needed.

From UILabel:

@property(nonatomic, copy) NSAttributedString *attributedText;

You just need to build up your NSAttributedString. There are basically two ways:

  1. Append chunks of text with the same attributes - for each part create one NSAttributedString instance and append them to one NSMutableAttributedString

  2. Create attributed text from plain string and then add attributed for given ranges – find the range of your number (or whatever) and apply different color attribute on that.

Tricertops
  • 8,492
  • 1
  • 39
  • 41
7

Anups answer in swift. Can be reused from any class.

In swift file

extension NSMutableAttributedString {

    func setColorForStr(textToFind: String, color: UIColor) {

        let range = self.mutableString.rangeOfString(textToFind, options:NSStringCompareOptions.CaseInsensitiveSearch);
        if range.location != NSNotFound {
            self.addAttribute(NSForegroundColorAttributeName, value: color, range: range);
        }

    }
}

In Some view controller

let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: self.labelShopInYourNetwork.text!);
attributedString.setColorForStr("YOUR NETWORK", color: UIColor(red: 0.039, green: 0.020, blue: 0.490, alpha: 1.0));
self.labelShopInYourNetwork.attributedText = attributedString;
Deepak Thakur
  • 3,453
  • 2
  • 37
  • 65
4

My answer has also the option to color all the occurrence of a text not only one occurrence of it : "wa ba wa ba dubdub" , you can color all the occurrence of wa not only the first occurrence like the accepted answer.

extension NSMutableAttributedString{
    func setColorForText(_ textToFind: String, with color: UIColor) {
        let range = self.mutableString.range(of: textToFind, options: .caseInsensitive)
        if range.location != NSNotFound {
            addAttribute(NSForegroundColorAttributeName, value: color, range: range)
        }
    }

    func setColorForAllOccuranceOfText(_ textToFind: String, with color: UIColor) {
        let inputLength = self.string.count
        let searchLength = textToFind.count
        var range = NSRange(location: 0, length: self.length)

        while (range.location != NSNotFound) {
            range = (self.string as NSString).range(of: textToFind, options: [], range: range)
            if (range.location != NSNotFound) {
                self.addAttribute(NSForegroundColorAttributeName, value: color, range: NSRange(location: range.location, length: searchLength))
                range = NSRange(location: range.location + range.length, length: inputLength - (range.location + range.length))
            }
        }
    }
}

Now you can do this :

let message = NSMutableAttributedString(string: "wa ba wa ba dubdub")
message.setColorForText(subtitle, with: UIColor.red) 
// or the below one if you want all the occurrence to be colored 
message.setColorForAllOccuranceOfText("wa", with: UIColor.red) 
// then you set this attributed string to your label :
lblMessage.attributedText = message
Mostafa Sultan
  • 2,268
  • 2
  • 20
  • 36
4

Having a UIWebView or more than one UILabel could be considered overkill for this situation.

My suggestion would be to use TTTAttributedLabel which is a drop-in replacement for UILabel that supports NSAttributedString. This means you can very easily apply differents styles to different ranges in a string.

4

For displaying short, formatted text that doesn't need to be editable, Core Text is the way to go. There are several open-source projects for labels that use NSAttributedString and Core Text for rendering. See CoreTextAttributedLabel or OHAttributedLabel for example.

omz
  • 53,243
  • 5
  • 129
  • 141
3

JTAttributedLabel (by mystcolor) lets you use the attributed string support in UILabel under iOS 6 and at the same time its JTAttributedLabel class under iOS 5 through its JTAutoLabel.

Johan Kool
  • 15,637
  • 8
  • 64
  • 81
3

Swift 4 and above: Inspired by anoop4real's solution, here's a String extension that can be used to generate text with 2 different colors.

extension String {

    func attributedStringForPartiallyColoredText(_ textToFind: String, with color: UIColor) -> NSMutableAttributedString {
        let mutableAttributedstring = NSMutableAttributedString(string: self)
        let range = mutableAttributedstring.mutableString.range(of: textToFind, options: .caseInsensitive)
        if range.location != NSNotFound {
            mutableAttributedstring.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
        }
        return mutableAttributedstring
    }
}

Following example changes color of asterisk to red while retaining original label color for remaining text.

label.attributedText = "Enter username *".attributedStringForPartiallyColoredText("*", with: #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1))
Maverick
  • 3,209
  • 1
  • 34
  • 40
3

NSAttributedString is the way to go. The following question has a great answer that shows you how to do it How do you use NSAttributedString

Community
  • 1
  • 1
werner
  • 859
  • 4
  • 8
2

There is a Swift 3.0 solution

extension UILabel{


    func setSubTextColor(pSubString : String, pColor : UIColor){
        let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: self.text!);
        let range = attributedString.mutableString.range(of: pSubString, options:NSString.CompareOptions.caseInsensitive)
        if range.location != NSNotFound {
            attributedString.addAttribute(NSForegroundColorAttributeName, value: pColor, range: range);
        }
        self.attributedText = attributedString

    }
}

And there is an example of call :

let colorString = " (string in red)"
self.mLabel.text = "classic color" + colorString
self.mLabel.setSubTextColor(pSubString: colorString, pColor: UIColor.red)
Kevin ABRIOUX
  • 16,507
  • 12
  • 93
  • 99
  • Hi, how do I do this if I want to add two different colorStrings? I tried using your example and just add another one, but it still only colors one of them.. – Erik Auranaune Jan 21 '17 at 18:27
  • Try this : let colorString = " (string in red)" let colorStringGreen = " (string in green)" self.mLabel.text = "classic color" + colorString + colorStringGreen self.mLabel.setSubTextColor(pSubString: colorString, pColor: UIColor.red) self.mLabel.setSubTextColor(pSubString: colorStringGreen, pColor: UIColor.green) – Kevin ABRIOUX Jan 21 '17 at 18:30
  • This is strange, it still doesn't change both: https://s24.postimg.org/ds0rpyyut/Screen_Shot_2017_01_21_at_19_52_51.png. – Erik Auranaune Jan 21 '17 at 18:54
  • A problem is that if the two strings are the same, it only colors one of them, look here: http://pastebin.com/FJZJTpp3. You have a fix for this aswell? – Erik Auranaune Jan 21 '17 at 19:23
2

For Xamarin users I have a static C# method where I pass in an array of strings, an array of UIColours and array of UIFonts (they will need to match in length). The attributed string is then passed back.

see:

public static NSMutableAttributedString GetFormattedText(string[] texts, UIColor[] colors, UIFont[] fonts) {

  NSMutableAttributedString attrString = new NSMutableAttributedString(string.Join("", texts));
  int position = 0;

  for (int i = 0; i < texts.Length; i++) {
    attrString.AddAttribute(new NSString("NSForegroundColorAttributeName"), colors[i], new NSRange(position, texts[i].Length));

    var fontAttribute = new UIStringAttributes {
      Font = fonts[I]
    };

    attrString.AddAttributes(fontAttribute, new NSRange(position, texts[i].Length));

    position += texts[i].Length;
  }

  return attrString;

}
aturan23
  • 4,798
  • 4
  • 28
  • 52
Craig Champion
  • 442
  • 9
  • 16
2

In my case I'm using Xcode 10.1. There is a option of switching between plain text and Attributed text in Label text in Interface Builder

enter image description here

Hope this may help someone else..!

BharathRao
  • 1,846
  • 1
  • 18
  • 28
  • 2
    It looks like XCode 11.0 broke the Attributed Text editor. So, I tried using TextEdit to create the text then pasted it into Xcode and it worked surprisingly well. – Brainware Nov 27 '19 at 08:16
0
extension UILabel{

    func setSubTextColor(pSubString : String, pColor : UIColor){


        let attributedString: NSMutableAttributedString = self.attributedText != nil ? NSMutableAttributedString(attributedString: self.attributedText!) : NSMutableAttributedString(string: self.text!);


        let range = attributedString.mutableString.range(of: pSubString, options:NSString.CompareOptions.caseInsensitive)
        if range.location != NSNotFound {
            attributedString.addAttribute(NSForegroundColorAttributeName, value: pColor, range: range);
        }
        self.attributedText = attributedString

    }
}
0

My own solution was created a method like the next one:

-(void)setColorForText:(NSString*) textToFind originalText:(NSString *)originalString withColor:(UIColor*)color andLabel:(UILabel *)label{

NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:originalString];
NSRange range = [originalString rangeOfString:textToFind];

[attString addAttribute:NSForegroundColorAttributeName value:color range:range];

label.attributedText = attString;

if (range.location != NSNotFound) {
    [attString addAttribute:NSForegroundColorAttributeName value:color range:range];
}
label.attributedText = attString; }

It worked with just one different color in the same text but you can adapt it easily to more colores in the same sentence.

shontauro
  • 1,812
  • 1
  • 25
  • 26
0

By using below code you can set multiple colors based on word.

NSMutableArray * array = [[NSMutableArray alloc] initWithObjects:@"1 ball",@"2 ball",@"3 ball",@"4 ball", nil];    
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] init];
for (NSString * str in array)
 {
    NSMutableAttributedString * textstr = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ ,",str] attributes:@{NSForegroundColorAttributeName :[self getRandomColor]}];
     [attStr appendAttributedString:textstr];
  }
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(10, 300, 300, 30)];
lab.attributedText = attStr;
[self.view addSubview:lab];

-(UIColor *) getRandomColor
{
   CGFloat redcolor = arc4random() % 255 / 255.0;
   CGFloat greencolor = arc4random() % 255 / 255.0;
   CGFloat bluencolor = arc4random() % 255 / 255.0;
   return  [UIColor colorWithRed:redcolor green:greencolor blue:bluencolor alpha:1.0];
}
Hari c
  • 1,139
  • 11
  • 11
0

SwiftRichString works perfect! You can use + to concatenate two attributed string

fujianjin6471
  • 5,168
  • 1
  • 36
  • 32