在 Swift 中的按钮文本下划线

我有 UIButton。在 Interface Builder 中,我将其标题设置为“署名”。在 Swift 中,如何使其标题在代码中加下划线?

@IBOutlet weak var myBtn: UIButton!

我创建了一个函数来调用这个按钮的 touch UpInside 事件:

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;

但还是没有结果。我还需要知道如何访问下划线属性。文字、大小和颜色保持不变。

108703 次浏览

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
]

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)
}

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)

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

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
}
}
}

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

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]

@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
}
}
}

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()
}

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

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

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
]
  • 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)

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)
}
}