Is it possible to set a different colour for one character in a UILabel?
Asked Answered
H

7

5

I've been working on a small project using Xcode. It uses a lot of labels, textfields, etc. I've finished with most of the layout, the constrains, and the forms, titles, etc. After which, the client announces that for all required fields, there should be a red asterisk next to the label.

Call me lazy, but I'd rather not go back to all of my forms, add in a lot of labels with asterisks on them, and re-do my auto-layout to accommodate the new labels.

So, is there a way to change the colour of a specific character (in this case, the asterisk) in a UILabel, while the rest of the text stays black?

Headley answered 15/1, 2016 at 9:47 Comment(3)
Look at using attributed strings which you can set to the label. This allows you to set different colours, as well as font sizes, etc.Colemancolemanite
NSMutableAttributedString does this for you. You can set different property for different range of string.Biff
Is the effort you would like to achieve it with requires a) not to touch layout code by adding some UILabel next to existed UILabels b) not to add asterisk manually to each string you assign to .text or .attributedText properties of UILabel? So, you just want some UILabel's extension or UILabel's subclass with red asterisk being added at the end of each UILabel you specify, don't you?Mucin
G
11

You can use NSMutableAttributedString. You can set specific range of your string with different color, font, size, ...

E.g:

 var range = NSRange(location:2,length:1) // specific location. This means "range" handle 1 character at location 2

 attributedString = NSMutableAttributedString(string: originalString, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 18.0)!])
 // here you change the character to red color
 attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)
 label.attributedText = attributedString

Ref: Use multiple font colors in a single label - Swift

You can change a lot of attribute of String. Ref from apple: https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSMutableAttributedString_Class/index.html

Glabella answered 15/1, 2016 at 9:57 Comment(3)
This code is copied straight from the top of the answer you're linking to, and in its current form, adds nothing that a comment linked to this thread couldn't have achieved, rather than an answer of your own. Hence, I downvoted this. If you however refine the answer and show the OP how to use this w.r.t. UILabel:s (which is his question), I will reverse my down-vote. See this meta thread, especially the part in the answer regarding effort by an answerer.Nomism
@dfri Thank you very much. It's really bad. Sorry. I updated my answer for more sense :). I was busy at that time. So I just want the OP see the answer at the link I found. Thank you. :)Glabella
You're welcome, and that's better, reversed my vote!Nomism
Q
9
let text = "Sample text *"
let range = (text as NSString).rangeOfString("*")
let attributedString = NSMutableAttributedString(string:text)
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor() , range: range)

    //Apply to the label
    myLabel.attributedText = attributedString;
Quantic answered 15/1, 2016 at 10:0 Comment(2)
Taken from an answer to this question without attribution.Hypnotism
if there is more then one () and I want change color of all () then what is do.Toxinantitoxin
N
4

UILabel have an .attributedText property of type NSAttributedString.

Declaration

@NSCopying var attributedText: NSAttributedString?

You let your asterix * have a single .redColor() attribute (NSForegroundColorAttributeName), whereas the rest of the new label simply uses the same text as before, however also contained in an NSAttributedTextString.

An example follows below using a function to repeatedly update your existing labels to attributed strings prefixed with a red *:

class ViewController: UIViewController {

    @IBOutlet weak var myFirstLabel: UILabel!
    @IBOutlet weak var mySecondLabel: UILabel!

    let myPrefixCharacter = "*"
    let myPrefixColor = UIColor.redColor()    

    // ...

    override func viewDidLoad() {
        super.viewDidLoad()

        // ...

        /* update labels to attributed strings */
        updateLabelToAttributedString(myFirstLabel)
        updateLabelToAttributedString(mySecondLabel)
        // ...

    }

    func updateLabelToAttributedString(label: UILabel) {

        /* original label text as NSAttributedString, prefixed with " " */
        let attr = [ NSForegroundColorAttributeName: myPrefixColor ]
        let myNewLabelText = NSMutableAttributedString(string: myPrefixCharacter, attributes: attr)
        let myOrigLabelText = NSAttributedString(string: " " + (label.text ?? ""))

        /* set new label text as attributed string */
        myNewLabelText.appendAttributedString(myOrigLabelText)
        label.attributedText = myNewLabelText
    }

    // ...

}

enter image description here

Nomism answered 15/1, 2016 at 10:7 Comment(0)
R
3

Swift 4
(Note: notation for attributed string key is changed in swift 4)

Here is an extension for NSMutableAttributedString, that add/set color on string/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)
    }

}

Now, try above extension with UILabel and see result

let label = UILabel()
label.frame = CGRect(x: 40, y: 100, width: 280, height: 200)
let red = "red"
let blue = "blue"
let green = "green"
let stringValue = "\(red)\n\(blue)\n&\n\(green)"
label.textColor = UIColor.lightGray
label.numberOfLines = 0
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: stringValue)
attributedString.setColor(color: UIColor.red, forText: red)   // or use direct value for text "red"
attributedString.setColor(color: UIColor.blue, forText: blue)   // or use direct value for text "blue"
attributedString.setColor(color: UIColor.green, forText: green)   // or use direct value for text "green"
label.font = UIFont.systemFont(ofSize: 26)
label.attributedText = attributedString
self.view.addSubview(label)
Ragland answered 12/1, 2018 at 11:24 Comment(0)
C
2
func updateAttributedStringWithCharacter(title : String, uilabel: UILabel) {
    let text = title + "*"
    let range = (text as NSString).range(of: "*")
    let attributedString = NSMutableAttributedString(string:text)
    attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)
    uilabel.attributedText = attributedString }
Confiscable answered 31/10, 2020 at 6:49 Comment(1)
updateAttributedStringWithCharacter(title: lbl_name.text!, uilabel: lbl_name) Use this function to show Star(*) after the label Note -: User above function in viewDidLoad() to get effect. Taken ref from @tuledev's answerConfiscable
B
1

I know this is an old post, but i want to share my approach (which is based on the answer from dfri) i just made it a function for convenience.

func lastCharOnColor(label: UILabel, color: UIColor, length: Int) {

    //First we get the text.
    let string = label.text

    //Get number of characters on string and based on that get last character index.
    let characterCounter    = string?.characters.count
    let lastCharacterIndex  = characterCounter!-1

    //Set Range
    let range = NSRange(location: lastCharacterIndex, length: length)
    let attributedString = NSMutableAttributedString(string: string!, attributes: nil)

    //Set label
    attributedString.addAttribute(NSForegroundColorAttributeName, value: color, range: range)
    label.attributedText = attributedString

}

I use this function to just set the last character from a label to a certain color like this:

        lastCharOnColor(label: self.labelname, color: UIColor.red, length: 1)

Hope this helps anyone.

Beograd answered 13/3, 2017 at 23:47 Comment(0)
D
0

Here is an extension for simply making mandatory labels by appending a red *

Swift 5

extension UILabel {
func makeTextMandatory() {
    let text = self.text ?? "" + " *"
    let range = (text as NSString).range(of: " *")
    let attributedString = NSMutableAttributedString(string:text)
    attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)
    self.attributedText = attributedString
  }
}

Usage :

dobLabel.makeTextMandatory()
Darien answered 1/3, 2022 at 11:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.