I\'m using iOS 6, so attributed strings should be easy to use, right? Well... not so much.
What I want to do:
Using a custom subclass of
With Swift 5.1 and iOS 13.1, you can use the UIButton
subclass implementation below in order to solve your problem:
import UIKit
class CustomButton: UIButton {
required init(title: String, subtitle: String) {
super.init(frame: CGRect.zero)
let style = NSMutableParagraphStyle()
style.alignment = NSTextAlignment.center
style.lineBreakMode = NSLineBreakMode.byWordWrapping
let titleAttributes: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.foregroundColor: UIColor.label,
NSAttributedString.Key.underlineStyle : NSUnderlineStyle.single.rawValue,
NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.largeTitle),
NSAttributedString.Key.paragraphStyle : style
]
let subtitleAttributes = [
NSAttributedString.Key.foregroundColor: UIColor.label,
NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body),
NSAttributedString.Key.paragraphStyle : style
]
let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes)
attributedString.append(NSAttributedString(string: "\n"))
attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes))
setAttributedTitle(attributedString, for: UIControl.State.normal)
titleLabel?.numberOfLines = 0
titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Usage:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = CustomButton(title: "Title", subtitle: "Subtitle")
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
}
}
As an alternative if you really need a button of type system
, you may use the following code:
import UIKit
extension UIButton {
static func customSystemButton(title: String, subtitle: String) -> UIButton {
let style = NSMutableParagraphStyle()
style.alignment = NSTextAlignment.center
style.lineBreakMode = NSLineBreakMode.byWordWrapping
let titleAttributes: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.underlineStyle : NSUnderlineStyle.single.rawValue,
NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.largeTitle),
NSAttributedString.Key.paragraphStyle : style
]
let subtitleAttributes = [
NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body),
NSAttributedString.Key.paragraphStyle : style
]
let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes)
attributedString.append(NSAttributedString(string: "\n"))
attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes))
let button = UIButton(type: UIButton.ButtonType.system)
button.setAttributedTitle(attributedString, for: UIControl.State.normal)
button.titleLabel?.numberOfLines = 0
button.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
return button
}
}
Usage:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton.customSystemButton(title: "Title", subtitle: "Subtitle")
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint])
}
}
The two screen shots below show the result display for the UIButton
subclass (on the left) and for the system
type button (on the right):