How to underline a UILabel in swift?
Asked Answered
S

16

144

How to underline a UILabel in Swift? I searched the Objective-C ones but couldn't quite get them to work in Swift.

Sour answered 20/1, 2015 at 19:10 Comment(5)
NSAttributedString?Explicable
whats with the dislikes? there is an obvious confusion here with the attibutes looking like method calls in objcSour
here You Can get the easy way #28268560Padraig
here are the easy way [#28268560Padraig
Better solution algorithm with better solution you can look my answer #28053834Ette
M
314

You can do this using NSAttributedString

Example:

let underlineAttribute = [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.thick.rawValue]
let underlineAttributedString = NSAttributedString(string: "StringWithUnderLine", attributes: underlineAttribute)
myLabel.attributedText = underlineAttributedString

EDIT

To have the same attributes for all texts of one UILabel, I suggest you to subclass UILabel and overriding text, like that:

Swift 5

Same as Swift 4.2 but: You should prefer the Swift initializer NSRange over the old NSMakeRange, you can shorten to .underlineStyle and linebreaks improve readibility for long method calls.

class UnderlinedLabel: UILabel {

override var text: String? {
    didSet {
        guard let text = text else { return }
        let textRange = NSRange(location: 0, length: text.count)
        let attributedText = NSMutableAttributedString(string: text)
        attributedText.addAttribute(.underlineStyle,
                                    value: NSUnderlineStyle.single.rawValue,
                                    range: textRange)
        // Add other attributes if needed
        self.attributedText = attributedText
        }
    }
}

Swift 4.2

class UnderlinedLabel: UILabel {

override var text: String? {
    didSet {
        guard let text = text else { return }
        let textRange = NSMakeRange(0, text.count)
        let attributedText = NSMutableAttributedString(string: text)
        attributedText.addAttribute(NSAttributedString.Key.underlineStyle , value: NSUnderlineStyle.single.rawValue, range: textRange)
        // Add other attributes if needed
        self.attributedText = attributedText
        }
    }
}

Swift 3.0

class UnderlinedLabel: UILabel {
    
    override var text: String? {
        didSet {
            guard let text = text else { return }
            let textRange = NSMakeRange(0, text.characters.count)
            let attributedText = NSMutableAttributedString(string: text)
            attributedText.addAttribute(NSUnderlineStyleAttributeName , value: NSUnderlineStyle.styleSingle.rawValue, range: textRange)
            // Add other attributes if needed
            self.attributedText = attributedText
        }
    }
}

And you put your text like this :

@IBOutlet weak var label: UnderlinedLabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        label.text = "StringWithUnderLine"
    }

OLD:

Swift (2.0 to 2.3):

class UnderlinedLabel: UILabel {
    
    override var text: String? {
        didSet {
            guard let text = text else { return }
            let textRange = NSMakeRange(0, text.characters.count)
            let attributedText = NSMutableAttributedString(string: text)
            attributedText.addAttribute(NSUnderlineStyleAttributeName, value:NSUnderlineStyle.StyleSingle.rawValue, range: textRange)
            // Add other attributes if needed
            
            self.attributedText = attributedText
        }
    }
}

Swift 1.2:

class UnderlinedLabel: UILabel {
    
    override var text: String! {
        didSet {
            let textRange = NSMakeRange(0, count(text))
            let attributedText = NSMutableAttributedString(string: text)
            attributedText.addAttribute(NSUnderlineStyleAttributeName, value:NSUnderlineStyle.StyleSingle.rawValue, range: textRange)
            // Add other attributes if needed
            
            self.attributedText = attributedText
        }
    }
}
Mccollum answered 20/1, 2015 at 19:30 Comment(5)
What would be the best way to de-underline?Quartered
I've been wondering for a long time: why do we have to use rawValue otherwise it crashes?Pantsuit
You should pass UTF16 count instead of the character count when creating your textRange NSRangeTedium
I've changed this solution to add a underlline on initialize, this way we can use it easily with storyboards required init?(coder: NSCoder) { super.init(coder: coder) self.addUnderline() // your code }Revitalize
Better solution algorithm with better solution you can look my answer #28053834Ette
T
128

Swift 5 & 4.2 one liner:

label.attributedText = NSAttributedString(string: "Text", attributes:
    [.underlineStyle: NSUnderlineStyle.single.rawValue])

Swift 4 one liner:

label.attributedText = NSAttributedString(string: "Text", attributes:
    [.underlineStyle: NSUnderlineStyle.styleSingle.rawValue])

Swift 3 one liner:

label.attributedText = NSAttributedString(string: "Text", attributes:
      [NSUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue])
Tartlet answered 25/3, 2017 at 11:38 Comment(3)
NSUnderlineStyle.styleSingle.rawValue has been renamed to NSUnderlineStyle.single.rawValue in swift 4.2Belleslettres
How do I de-underline?Quartered
@N.Der Set again a normal text to labelGoto
P
31

Swift 5:

1- Create a String extension to get attributedText

extension String {

    var underLined: NSAttributedString {
        NSMutableAttributedString(string: self, attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue])
    }

}

2- Use it

On buttons:

<#YourButton#>.setAttributedTitle(<#YourButtonTitle#>.underLined, for: .normal)

On Labels:

<#YourLabel#>.attributedText = <#YourLabelTitle#>.underLined

Or Stoyboard version

Penn answered 6/6, 2018 at 9:8 Comment(1)
The above extension worked out for me, thanks.Eponym
S
24

If you are looking for a way to do this without inheritance:

Swift 5

extension UILabel {
    func underline() {
        if let textString = self.text {
          let attributedString = NSMutableAttributedString(string: textString)
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle,
                                          value: NSUnderlineStyle.single.rawValue,
                                          range: NSRange(location: 0, length: attributedString.length))
          attributedText = attributedString
        }
    }
}

Swift 3/4

// in swift 4 - switch NSUnderlineStyleAttributeName with NSAttributedStringKey.underlineStyle
extension UILabel {
    func underline() {
        if let textString = self.text {
          let attributedString = NSMutableAttributedString(string: textString)
          attributedString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: NSRange(location: 0, length: attributedString.length))
          attributedText = attributedString
        }
    }
}


extension UIButton {
  func underline() {
    let attributedString = NSMutableAttributedString(string: (self.titleLabel?.text!)!)
    attributedString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: NSRange(location: 0, length: (self.titleLabel?.text!.characters.count)!))
    self.setAttributedTitle(attributedString, for: .normal)
  }
}
Santinasantini answered 21/8, 2017 at 7:52 Comment(1)
You should pass UTF16 count instead of the character count when creating your NSRangeTedium
H
9

Just a little fix for the Shlome answer in Swift 4 and Xcode 9.

extension UILabel {
    func underline() {
        if let textString = self.text {
            let attributedString = NSMutableAttributedString(string: textString)
            attributedString.addAttribute(NSAttributedStringKey.underlineStyle,
                                          value: NSUnderlineStyle.styleSingle.rawValue,
                                          range: NSRange(location: 0, length: attributedString.length - 1))
            attributedText = attributedString
        }
    }
}

    extension UIButton {
        func underline() {
            let attributedString = NSMutableAttributedString(string: (self.titleLabel?.text!)!)
            attributedString.addAttribute(NSAttributedStringKey.underlineStyle,
                                          value: NSUnderlineStyle.styleSingle.rawValue,
                                          range: NSRange(location: 0, length: (self.titleLabel?.text!.count)!))
            self.setAttributedTitle(attributedString, for: .normal)
        }
    }
Headrest answered 2/11, 2017 at 16:38 Comment(1)
You should pass UTF16 count instead of the character count when creating your NSRangeTedium
C
7

You can underline the UILabel text using Interface Builder.

Here is the link of my answer : Adding underline attribute to partial text UILabel in storyboard

Cima answered 10/6, 2015 at 7:51 Comment(2)
This method fails if you rebind the text to the label.Dailey
@EricH What do you mean?Levenson
B
7

Same Answer in Swift 4.2

For UILable

extension UILabel {
    func underline() {
        if let textString = self.text {
            let attributedString = NSMutableAttributedString(string: textString)
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle,
                                          value: NSUnderlineStyle.single.rawValue,
                                          range: NSRange(location: 0, length: textString.count))
            self.attributedText = attributedString
        }
    }
}

Call for UILabel like below

myLable.underline()

For UIButton

extension UIButton {
    func underline() {
        if let textString = self.titleLabel?.text {

            let attributedString = NSMutableAttributedString(string: textString)
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle,
                                          value: NSUnderlineStyle.single.rawValue,
                                          range: NSRange(location: 0, length: textString.count))
            self.setAttributedTitle(attributedString, for: .normal)
        }

    }
}

Call for UIButton like below

myButton.underline()

I looked into above answers and some of them are force unwrapping text value. I will suggest to get value by safely unwrapping. This will avoid crash in case of nil value. Hope This helps :)

Barnard answered 22/9, 2018 at 13:27 Comment(3)
simply beutiful and easyPhototube
You should pass UTF16 count instead of the character count when creating your NSRangeTedium
If you already have the extension for the UILabel, IMO it is simpler to call myButton.titleLabel?.underline(), or at least use it inside the underline() function in the extension for UIButton.Hwahwan
D
6

Swift 4, 4.2 and 5.

  @IBOutlet weak var lblUnderLine: UILabel!

I need to underline particular text in UILabel. So, find range and set attributes.

    let strSignup = "Don't have account? SIGNUP NOW."
    let rangeSignUp = NSString(string: strSignup).range(of: "SIGNUP NOW.", options: String.CompareOptions.caseInsensitive)
    let rangeFull = NSString(string: strSignup).range(of: strSignup, options: String.CompareOptions.caseInsensitive)
    let attrStr = NSMutableAttributedString.init(string:strSignup)
    attrStr.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.white,
                           NSAttributedString.Key.font : UIFont.init(name: "Helvetica", size: 17)! as Any],range: rangeFull)
    attrStr.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.white,
                           NSAttributedString.Key.font : UIFont.init(name: "Helvetica", size: 20)!,
                          NSAttributedString.Key.underlineStyle: NSUnderlineStyle.thick.rawValue as Any],range: rangeSignUp) // for swift 4 -> Change thick to styleThick
    lblUnderLine.attributedText = attrStr

Output

enter image description here

Dorri answered 15/7, 2019 at 11:52 Comment(0)
W
4

Underline to multiple strings in a sentence.

extension UILabel {
    func underlineMyText(range1:String, range2:String) {
        if let textString = self.text {

            let str = NSString(string: textString)
            let firstRange = str.range(of: range1)
            let secRange = str.range(of: range2)
            let attributedString = NSMutableAttributedString(string: textString)
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: firstRange)
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: secRange)
            attributedText = attributedString
        }
    }
}

Use by this way.

    lbl.text = "By continuing you agree to our Terms of Service and Privacy Policy."
    lbl.underlineMyText(range1: "Terms of Service", range2: "Privacy Policy.")
Woodwork answered 17/4, 2019 at 12:57 Comment(1)
How you will track the touch?Passant
W
2

Swift 4 changes. Remeber to use NSUnderlineStyle.styleSingle.rawValue instead of NSUnderlineStyle.styleSingle.

   'let attributedString = NSAttributedString(string: "Testing")
    let textRange = NSMakeRange(0, attributedString.length)
    let underlinedMessage = NSMutableAttributedString(attributedString: attributedString)
    underlinedMessage.addAttribute(NSAttributedStringKey.underlineStyle,
                                   value:NSUnderlineStyle.styleSingle.rawValue,
                                   range: textRange)
    label.attributedText = underlinedMessage

`

Warfeld answered 26/9, 2017 at 7:34 Comment(0)
S
2

You can use this also if you want to achieve only half part of label as underline:- //For Swift 4.0+

let attributesForUnderLine: [NSAttributedString.Key: Any] = [
            .font: UIFont(name: AppFont.sourceSansPro_Regular, size: 12) ?? UIFont.systemFont(ofSize: 11),
            .foregroundColor: UIColor.blue,
            .underlineStyle: NSUnderlineStyle.single.rawValue]

        let attributesForNormalText: [NSAttributedString.Key: Any] = [
            .font: UIFont(name: AppFont.sourceSansPro_Regular, size: 12) ?? UIFont.systemFont(ofSize: 11),
            .foregroundColor: AppColors.ColorText_787878]

        let textToSet = "Want to change your preferences? Edit Now"
        let rangeOfUnderLine = (textToSet as NSString).range(of: "Edit Now")
        let rangeOfNormalText = (textToSet as NSString).range(of: "Want to change your preferences?")

        let attributedText = NSMutableAttributedString(string: textToSet)
        attributedText.addAttributes(attributesForUnderLine, range: rangeOfUnderLine)
        attributedText.addAttributes(attributesForNormalText, range: rangeOfNormalText)
        yourLabel.attributedText = attributedText
Salientian answered 13/6, 2019 at 7:6 Comment(0)
G
1

The answer above is causing an error in my build environment.

This doesn't work in Swift 4.0:

attributedText.addAttribute(NSUnderlineStyleAttributeName, 
                            value: NSUnderlineStyle.styleSingle.rawValue, 
                            range: textRange)

Try this instead:

attributedText.addAttribute(NSAttributedStringKey.underlineStyle,
                            value: NSUnderlineStyle.styleSingle.rawValue,
                            range: textRange)

hope this helps someone.

Goldbrick answered 25/10, 2017 at 15:3 Comment(0)
T
1

// Swift 4 Version

 let attributedString  = NSMutableAttributedString(string: "Your Text Here", attributes: [NSAttributedStringKey.underlineStyle : true])

self.yourlabel.attributedText = attributedString
Timms answered 1/6, 2018 at 12:32 Comment(0)
D
1

A class to set and remove underline for UIbuttons for Swift 5. I hope this helps

import Foundation
   import UIKit

   class UiUtil {

       static let underlineThickness = 2
    
       class func removeUnderlineFromButton( _ button:UIButton ) {
          if let str = button.titleLabel?.attributedText {
            let attributedString = NSMutableAttributedString( attributedString: str )
            attributedString.removeAttribute(.underlineStyle, range: 
   NSRange.init(location: 0, length: attributedString.length))
            button.setAttributedTitle(attributedString, for: .normal)
         }
      }

    class func setUnderlineFromButton( _ button:UIButton ) {
        if let str = button.titleLabel?.attributedText {
            let attributedStringUnderline = NSMutableAttributedString( attributedString: 
    str  )
              attributedStringUnderline.addAttribute(
                NSAttributedString.Key.underlineStyle,
                value: underlineThickness,
                range: NSRange.init(location: 0, length: attributedStringUnderline.length)
              )
              button.setAttributedTitle(attributedStringUnderline, for: .normal)
           }
      }

   }
Delphine answered 26/6, 2020 at 7:9 Comment(0)
E
1

I have algorithm that used in my app. In this algorithm you can underline substring even that have space between words

extension NSMutableAttributedString{

    static func  findSubStringAndUnderlineIt(subStringToBeFound : String,totalString : String)->  NSMutableAttributedString?{
        
        let attributedString = NSMutableAttributedString(string: totalString)

        var spaceCount = 0
        
        if subStringToBeFound.contains(" "){
            spaceCount = subStringToBeFound.components(separatedBy:" ").count-1
        }

        
        if  let range = attributedString.string.range(of: subStringToBeFound, options: .caseInsensitive){
        
            attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: NSMakeRange((range.lowerBound.utf16Offset(in: subStringToBeFound)) ,(range.upperBound.utf16Offset(in: subStringToBeFound)) +
            spaceCount))
                return attributedString
        }
        return attributedString
        
    }
    
}

in used section

 lblWarning.attributedText = NSMutableAttributedString.findSubStringAndUnderlineIt(subStringToBeFound:"Not: Sadece uygulamanın reklamları kaldırılacaktır.", totalString: lblWarning.text!)
Ette answered 3/12, 2020 at 8:51 Comment(0)
D
0

For Swift 2.3

extension UIButton {
    func underline() {
        let attributedString = NSMutableAttributedString(string: (self.titleLabel?.text!)!)
        attributedString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: NSRange(location: 0, length: (self.titleLabel?.text!.characters.count)!))
        self.setAttributedTitle(attributedString, forState: .Normal)
    }
}

and in ViewController

@IBOutlet var yourButton: UIButton!

in ViewDidLoad Method or in your function just write

yourButton.underline()

it will underline the title of your button

Deactivate answered 1/3, 2018 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.