[ad_1]
There is no common reply as a result of every state of affairs is exclusive, however typically there are a number of widespread patterns:
- Implement a manufacturing unit methodology that might create a button, arrange all its properties and return it.
- Subclass
UIButton
and add new conduct and affordable defaults. - Subclass
UIControl
for one thing completely customized, like a management that’s composed out a number of different views.
Now, your explicit drawback appears to be implementing a reusable button with two in another way styled traces of textual content inside.
Including labels as subviews to UIButton
is one thing I undoubtedly would not suggest. This breaks accessiblity and you will have to do a variety of work to help totally different button states like highlighted or disabled.
As a substitute, I extremely suggest to utilize a fantastic function of UIButton
: it helps attributed strings for title, and titles may be multiline as properly as a result of you could have entry to the button’s titleLabel
property.
Subclassing UIButton
only for affordable defaults and ease of setup looks as if a good selection right here:
struct TwoLineButtonModel {
let title: String
let subtitle: String
let motion: () -> Void
}
remaining class TwoLineButton: UIButton {
non-public var motion: (() -> Void)?
override init(body: CGRect) {
tremendous.init(body: body)
addTarget(self, motion: #selector(handleTap(_:)), for: .touchUpInside)
setUpAppearance()
}
@obtainable(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been carried out")
}
func configure(with mannequin: TwoLineButtonModel) {
[.normal, .highlighted, .disabled].forEach {
setAttributedTitle(
makeButtonTitle(
title: mannequin.title,
subtitle: mannequin.subtitle,
forState: $0
),
for: $0
)
}
motion = mannequin.motion
}
@objc non-public func handleTap(_ sender: Any) {
motion?()
}
non-public func setUpAppearance() {
backgroundColor = .yellow
layer.cornerRadius = 16
titleLabel?.numberOfLines = 0
contentEdgeInsets = UIEdgeInsets(high: 16, left: 8, backside: 16, proper: 8)
}
non-public func makeButtonTitle(
title: String,
subtitle: String,
forState state: UIControl.State
) -> NSAttributedString {
let centeredParagraphStyle = NSMutableParagraphStyle()
centeredParagraphStyle.alignment = .middle
let primaryColor: UIColor = {
change state {
case .highlighted:
return .label.withAlphaComponent(0.5)
case .disabled:
return .label.withAlphaComponent(0.3)
default:
return .label
}
}()
let secondaryColor: UIColor = {
change state {
case .highlighted:
return .secondaryLabel.withAlphaComponent(0.3)
case .disabled:
return .secondaryLabel.withAlphaComponent(0.1)
default:
return .secondaryLabel
}
}()
let elements = [
NSAttributedString(
string: title + "n",
attributes: [
.font: UIFont.preferredFont(forTextStyle: .title1),
.foregroundColor: primaryColor,
.paragraphStyle: centeredParagraphStyle
]
),
NSAttributedString(
string: subtitle,
attributes: [
.font: UIFont.preferredFont(forTextStyle: .body),
.foregroundColor: secondaryColor,
.paragraphStyle: centeredParagraphStyle
]
)
]
let string = NSMutableAttributedString()
elements.forEach { string.append($0) }
return string
}
}
The textual content types and colours in my instance could not precisely match what you want, however it’s simply adjustable and you’ll take it from right here. Transfer issues that must be customizable into the view mannequin whereas conserving the affordable defaults as a personal implementation. Look into tutorials on NSAttributedString
in case you’re not but aware of it, it offers you a variety of freedom in styling texts.
[ad_2]