moonvader
moonvader

Reputation: 21131

Underline button text in Swift

I have UIButton. In interface builder I set its title to be 'Attributed'. How can I make its title to be underlined from code in Swift?

@IBOutlet weak var myBtn: UIButton!

I created a function called on the touchUpInside event of this button:

var attributedString = NSMutableAttributedString(string:"new text")
    var attrs = [
        NSFontAttributeName : UIFont.systemFontOfSize(19.0),
        NSForegroundColorAttributeName : UIColor.redColor()
    ]
    var gString = NSMutableAttributedString(string:"g", attributes:attrs)
    attributedString.appendAttributedString(gString)

    myBtn.titleLabel?.attributedText = attributedString;

But still no result. Also I need to know how to access the underline attribute. Text, size and color stay the same.

Upvotes: 104

Views: 124931

Answers (15)

shubham sharma
shubham sharma

Reputation: 1

I did it with using attribute in storyboard but not worked This Worked For me -

Edited -

func setUnderlineForButton(_ button: UIButton, text: String, color: UIColor, fontSize: CGFloat) {
        let attributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.boldSystemFont(ofSize: fontSize),
            .underlineStyle: NSUnderlineStyle.single.rawValue,
            .foregroundColor: color
        ]

        let attributedText = NSAttributedString(string: text, attributes: attributes)
        button.setAttributedTitle(attributedText, for: .normal)
    }
    

it will work in all device

Upvotes: -2

A.Kant
A.Kant

Reputation: 2970

Swift 5 / Xcode 12/13

  @IBOutlet weak var myButton: UIButton!
   
  let yourAttributes: [NSAttributedString.Key: Any] = [
      .font: UIFont.systemFont(ofSize: 14),
      .foregroundColor: UIColor.blue,
      .underlineStyle: NSUnderlineStyle.single.rawValue
  ] // .double.rawValue, .thick.rawValue
         
  
  override func viewDidLoad() {
     super.viewDidLoad()
    
     let attributeString = NSMutableAttributedString(
        string: "Your button text",
        attributes: yourAttributes
     )
     myButton.setAttributedTitle(attributeString, for: .normal)
  }

Swift 4 / Xcode 9

  @IBOutlet weak var myButton: UIButton!
   
  let yourAttributes: [NSAttributedStringKey: Any] = [
      NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14),
      NSAttributedStringKey.foregroundColor: UIColor.blue,
      NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleSingle.rawValue
  ] // .styleDouble.rawValue, .styleThick.rawValue, .styleNone.rawValue             
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    let attributeString = NSMutableAttributedString(
      string: "Your button text",
      attributes: yourAttributes
    )
    myButton.setAttributedTitle(attributeString, for: .normal)
  }

Swift 3 / Xcode 8

  @IBOutlet weak var myButton: UIButton!

  let yourAttributes: [String: Any] = [
      NSFontAttributeName: UIFont.systemFont(ofSize: 14),
      NSForegroundColorAttributeName: UIColor.white,
      NSUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue
  ] // .styleDouble.rawValue, .styleThick.rawValue, .styleNone.rawValue             

   override func viewDidLoad() {
      super.viewDidLoad()

      let attributeString = NSMutableAttributedString(
        string: "Your button text",
        attributes: yourAttributes
      )        
      myButton.setAttributedTitle(attributeString, for: .normal) 
    }

enter image description here

Upvotes: 169

AshWinee Dhakad
AshWinee Dhakad

Reputation: 681

A modified version of @shlomo-koppel answer for button title, It will work if you set/change button title programmatically (like in my case I used localization)

extension UIButton {
    func underline() {
        guard let text = self.currentTitle else { return }
        let attributedString = NSMutableAttributedString(string: text)
        attributedString.addAttribute(NSAttributedString.Key.underlineColor, value: self.titleColor(for: .normal)!, range: NSRange(location: 0, length: text.count))
        attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: self.titleColor(for: .normal)!, range: NSRange(location: 0, length: text.count))
        attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: NSRange(location: 0, length: text.count))
        self.setAttributedTitle(attributedString, for: .normal)
    }
}

Upvotes: 8

hectorsvill
hectorsvill

Reputation: 881

  • Swift 5.2.4
  • Xcode 11.5
let attributes: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.underlineStyle: 1,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13),
NSAttributedString.Key.foregroundColor: UIColor.systemGray3
]

let attributedString = NSMutableAttributedString(string: "Text here", attributes: attributes)
button.setAttributedTitle(NSAttributedString(attributedString: attributedString), for: .normal)

Upvotes: 8

Talha Rasool
Talha Rasool

Reputation: 1152

For swift 5

var attrs : [NSAttributedString.Key : Any] = [
    NSAttributedString.Key.font : UIFont.systemFont(ofSize: 19.0),
    NSAttributedString.Key.foregroundColor : UIColor.blue,
    NSAttributedString.Key.underlineStyle : NSUnderlineStyle.styleSingle.rawValue
]

Upvotes: 2

Andres Paladines
Andres Paladines

Reputation: 1218

May not be the best approach but I made an example to use it with a separated class and make only a one line call to get the text.

Here is my class:

import Foundation
import UIKit

enum AttributedTextsType {
    case underlined
    case bold
    case boldUnderlined
}

class AttributedTexts {
    private static func underlinedText(color: UIColor, size: CGFloat) -> [NSAttributedString.Key : Any] {
    let attrs = [
        NSAttributedString.Key.font : UIFont.systemFont(ofSize: size),
        NSAttributedString.Key.foregroundColor : color,
        NSAttributedString.Key.underlineStyle : 1] as [NSAttributedString.Key : Any]
    return attrs
    }

    private static func getAttibute(type: AttributedTextsType, color: UIColor, size: CGFloat) -> [NSAttributedString.Key : Any] {
        var attributes: [NSAttributedString.Key : Any]!
        switch type {
        case .underlined:
            attributes = AttributedTexts.underlinedText(color: color, size: size)
            break
        case .bold:
            attributes = AttributedTexts.underlinedText(color: color, size: size)
            break
        case .boldUnderlined:
            attributes = AttributedTexts.underlinedText(color: color, size: size)
            break
        }
        return attributes
    }

    static func set(string: String, color: UIColor, type: AttributedTextsType, size: CGFloat = 19.0) -> NSMutableAttributedString {
        let attributes = getAttibute(type: type, color: color, size: size)
        let attributedString = NSMutableAttributedString(string:"")
        let buttonTitleStr = NSMutableAttributedString(string: string, attributes: attributes)
        attributedString.append(buttonTitleStr)
        return attributedString
    }
}

Usage let attributedString = AttributedTexts.set(string: "Skip", color: .white, type: .underlined, size: 19.0)

Best regards

Upvotes: 0

Shlomo Koppel
Shlomo Koppel

Reputation: 945

if you are looking for a way to do this without inheritance -

swift 3/4/5

// in swift 4 - switch NSUnderlineStyleAttributeName with NSAttributedStringKey.underlineStyle

extension UIButton {
    func underline() {
        guard let text = self.titleLabel?.text else { return }
        let attributedString = NSMutableAttributedString(string: text)
        //NSAttributedStringKey.foregroundColor : UIColor.blue
        attributedString.addAttribute(NSAttributedString.Key.underlineColor, value: self.titleColor(for: .normal)!, range: NSRange(location: 0, length: text.count))
        attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: self.titleColor(for: .normal)!, range: NSRange(location: 0, length: text.count))
        attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: NSRange(location: 0, length: text.count))
        self.setAttributedTitle(attributedString, for: .normal)
    }
}



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 - 1))
            attributedText = attributedString
        }
    }
}

Upvotes: 36

Sukh
Sukh

Reputation: 1408

StoryBoard: If you want to Underline text from storyBoard.

  • Select button or label title as Attributed.
  • Select range of text which you want to underline.
  • Right click and choose Font then select underline.

enter image description here

Upvotes: 55

Kiran Jasvanee
Kiran Jasvanee

Reputation: 6564

@ShlomoKoppel answer in Swift 4.2

extension UIButton {
    func underline() {
        guard let text = self.titleLabel?.text else { return }
        let attributedString = NSMutableAttributedString(string: text)
        //NSAttributedStringKey.foregroundColor : UIColor.blue
        attributedString.addAttribute(NSAttributedString.Key.underlineColor, value: self.titleColor(for: .normal)!, range: NSRange(location: 0, length: text.count))
        attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: self.titleColor(for: .normal)!, range: NSRange(location: 0, length: text.count))
        attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: NSRange(location: 0, length: text.count))
        self.setAttributedTitle(attributedString, for: .normal)
    }
}



extension UILabel {
    func underlineMyText() {
        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 - 1))
            attributedText = attributedString
        }
    }
}

Upvotes: 12

Chong Hann
Chong Hann

Reputation: 89

Here is done on the storyboard. (Xcode 9.1)

  1. Select the Button object in your view.
  2. Open Fonts Settings

enter image description here

  1. Select Single Underline

enter image description here

  1. Type your text, press [Enter]

Upvotes: 8

tBug
tBug

Reputation: 826

This is my solution. And to be honest you probably need this more than one place, so let's create an extension. This is swift 5.0 Cheers :)

extension UIButton {
    func underline() {
        guard let title = self.titleLabel else { return }
        guard let tittleText = title.text else { return }
        let attributedString = NSMutableAttributedString(string: (tittleText))
        attributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: NSRange(location: 0, length: (tittleText.count)))
        self.setAttributedTitle(attributedString, for: .normal)
    }
}

And you can use it like this.

    override func viewDidLoad() {
     super.viewDidLoad()
     button.underline()
}

Upvotes: 6

Max Tymchii
Max Tymchii

Reputation: 836

Based on some of previous answers I decide to make a class that can be easy implemented into your apps

Swift 4

import UIKit

class UnderlineTextButton: UIButton {

override func setTitle(_ title: String?, for state: UIControlState) {
    super.setTitle(title, for: .normal)
    self.setAttributedTitle(self.attributedString(), for: .normal)
}

private func attributedString() -> NSAttributedString? {
    let attributes : [NSAttributedStringKey : Any] = [
        NSAttributedStringKey.font : UIFont.systemFont(ofSize: 19.0),
        NSAttributedStringKey.foregroundColor : UIColor.red,
        NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue
    ]
    let attributedString = NSAttributedString(string: self.currentTitle!, attributes: attributes)
    return attributedString
  }
}

From code I call it on such a way button.setTitle(author, for: .normal)

Upvotes: 20

Glorfindel
Glorfindel

Reputation: 22661

Thanks for posting your code, it wasn't clear that you knew how to create an attributed string at all.

This should work:

var attrs = [
    NSFontAttributeName : UIFont.systemFontOfSize(19.0),
    NSForegroundColorAttributeName : UIColor.redColor(),
    NSUnderlineStyleAttributeName : NSUnderlineStyle.StyleSingle.rawValue
]

Swift 4 version:

var attrs : [NSAttributedStringKey : Any] = [
    NSAttributedStringKey.font : UIFont.systemFont(ofSize: 19.0),
    NSAttributedStringKey.foregroundColor : UIColor.red,
    NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue
]

Upvotes: 15

Azharhussain Shaikh
Azharhussain Shaikh

Reputation: 1664

Here you can add an underline and bold face too. You can just add an extention in your swift class file

Here is the extention (Swift 4 updated)

extension NSMutableAttributedString {
 @discardableResult func bold(_ text:String) -> NSMutableAttributedString {

      let attrs : [NSAttributedStringKey : Any] = [
        NSAttributedStringKey.font : UIFont(name: "Montserrat-Bold", size: 12)!,
        NSAttributedStringKey.foregroundColor : UIColor.white,
        NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue]
    let boldString = NSMutableAttributedString(string: text, attributes: attrs)
    self.append(boldString)
    return self
 }

 @discardableResult func normal(_ text:String)->NSMutableAttributedString {
      let attrs : [NSAttributedStringKey : Any] = [
        NSAttributedStringKey.font : UIFont(name: "Montserrat-Regular", size: 12)!,
        NSAttributedStringKey.foregroundColor : UIColor.white
    ]
    let normal =  NSAttributedString(string: text,  attributes:attrs)
    self.append(normal)
    return self
 }

}

You can use it like this:

let FormattedText = NSMutableAttributedString()
      FormattedText
           .normal("By signing in, you agree with our ")
           .bold("Terms of Service")

yourLabel.attributedText = FormattedText

and the Result will be display like this enter image description here

Upvotes: 1

36 By Design
36 By Design

Reputation: 3271

Here you go, just tested it. (works in xCode 7 Beta at least)

@IBOutlet weak var yourButton: UIButton!

var attrs = [
NSFontAttributeName : UIFont.systemFontOfSize(19.0),
NSForegroundColorAttributeName : UIColor.redColor(),
NSUnderlineStyleAttributeName : 1]

var attributedString = NSMutableAttributedString(string:"")

override func viewDidLoad() {
  super.viewDidLoad()

  let buttonTitleStr = NSMutableAttributedString(string:"My Button", attributes:attrs)
  attributedString.appendAttributedString(buttonTitleStr)
  yourButton.setAttributedTitle(attributedString, forState: .Normal)
}

Upvotes: 103

Related Questions