Signal-iOS/SignalUI/Views/OWSFlatButton.swift
Adam Sharp b42710cf90 Work around use of deprecated UIButton API
The old UIButton API is still functional as long as we don't use
UIButton.Configuration, so we can safely ignore these warnings until we're
ready to adopt the configuration API across the codebase.
2024-07-03 14:27:48 -04:00

288 lines
8.6 KiB
Swift

//
// Copyright 2017 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import SignalServiceKit
import UIKit
public class OWSFlatButton: UIView {
public let button: UIButton
private var pressedBlock: (() -> Void)?
private var upColor: UIColor?
private var downColor: UIColor?
public var cornerRadius: CGFloat {
get {
button.layer.cornerRadius
}
set {
button.layer.cornerRadius = newValue
button.clipsToBounds = newValue > 0
}
}
public override var accessibilityIdentifier: String? {
didSet {
guard let accessibilityIdentifier = self.accessibilityIdentifier else {
return
}
button.accessibilityIdentifier = "\(accessibilityIdentifier).button"
}
}
override public var backgroundColor: UIColor? {
willSet {
owsFailDebug("Use setBackgroundColors(upColor:) instead.")
}
}
public var titleEdgeInsets: UIEdgeInsets {
get {
return button.ows_titleEdgeInsets
}
set {
button.ows_titleEdgeInsets = newValue
}
}
public var contentEdgeInsets: UIEdgeInsets {
get {
return button.ows_contentEdgeInsets
}
set {
button.ows_contentEdgeInsets = newValue
}
}
public override var tintColor: UIColor! {
get {
return button.tintColor
}
set {
button.tintColor = newValue
}
}
public init() {
AssertIsOnMainThread()
button = UIButton(type: .custom)
super.init(frame: CGRect.zero)
createContent()
}
@available(*, unavailable, message: "use other constructor instead.")
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func createContent() {
self.addSubview(button)
button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
button.autoPinEdgesToSuperviewEdges()
}
public class func button(title: String,
font: UIFont,
titleColor: UIColor,
backgroundColor: UIColor,
width: CGFloat,
height: CGFloat,
target: Any,
selector: Selector) -> OWSFlatButton {
let button = OWSFlatButton()
button.setTitle(title: title,
font: font,
titleColor: titleColor )
button.setBackgroundColors(upColor: backgroundColor)
button.useDefaultCornerRadius()
button.setSize(width: width, height: height)
button.addTarget(target: target, selector: selector)
return button
}
public class func button(title: String,
titleColor: UIColor,
backgroundColor: UIColor,
width: CGFloat,
height: CGFloat,
target: Any,
selector: Selector) -> OWSFlatButton {
return OWSFlatButton.button(title: title,
font: fontForHeight(height),
titleColor: titleColor,
backgroundColor: backgroundColor,
width: width,
height: height,
target: target,
selector: selector)
}
public class func button(title: String,
font: UIFont,
titleColor: UIColor,
backgroundColor: UIColor,
target: Any,
selector: Selector) -> OWSFlatButton {
return OWSFlatButton.button(
title: title,
font: font,
titleColor: titleColor,
backgroundColor: backgroundColor,
target: target,
selector: selector,
cornerRadius: .defaultCornerStyle
)
}
public class func insetButton(
title: String,
font: UIFont,
titleColor: UIColor,
backgroundColor: UIColor,
target: Any,
selector: Selector
) -> OWSFlatButton {
return OWSFlatButton.button(
title: title,
font: font,
titleColor: titleColor,
backgroundColor: backgroundColor,
target: target,
selector: selector,
cornerRadius: .insetCornerStyle
)
}
public class func button(
title: String,
font: UIFont,
titleColor: UIColor,
backgroundColor: UIColor,
target: Any,
selector: Selector,
cornerRadius: CGFloat
) -> OWSFlatButton {
let button = OWSFlatButton()
button.setTitle(title: title,
font: font,
titleColor: titleColor )
button.setBackgroundColors(upColor: backgroundColor)
button.addTarget(target: target, selector: selector)
button.layer.cornerRadius = cornerRadius
button.clipsToBounds = true
return button
}
public class func fontForHeight(_ height: CGFloat) -> UIFont {
// Cap the "button height" at 40pt or button text can look
// excessively large.
let fontPointSize = round(min(40, height) * 0.45)
return UIFont.semiboldFont(ofSize: fontPointSize)
}
public class func heightForFont(_ font: UIFont) -> CGFloat {
font.lineHeight * 2.5
}
// MARK: Methods
public func setTitleColor(_ color: UIColor) {
button.setTitleColor(color, for: .normal)
}
public func setTitle(title: String? = nil, font: UIFont? = nil, titleColor: UIColor? = nil) {
title.map { button.setTitle($0, for: .normal) }
font.map { button.titleLabel?.font = $0 }
titleColor.map { setTitleColor($0) }
}
public func setAttributedTitle(_ title: NSAttributedString) {
button.setAttributedTitle(title, for: .normal)
}
public func setImage(_ image: UIImage) {
button.setImage(image, for: .normal)
}
public func setBackgroundColors(upColor: UIColor,
downColor: UIColor ) {
button.setBackgroundImage(UIImage.image(color: upColor), for: .normal)
button.setBackgroundImage(UIImage.image(color: downColor), for: .highlighted)
}
public func setBackgroundColors(upColor: UIColor) {
let downColor = upColor == .clear ? upColor : upColor.withAlphaComponent(0.7)
setBackgroundColors(upColor: upColor, downColor: downColor)
}
public func setSize(width: CGFloat, height: CGFloat) {
button.autoSetDimension(.width, toSize: width)
button.autoSetDimension(.height, toSize: height)
}
public func useDefaultCornerRadius() {
// To my eye, this radius tends to look right regardless of button size
// (within reason) or device size.
button.layer.cornerRadius = 5
button.clipsToBounds = true
}
public func useInsetCornerRadius() {
button.layer.cornerRadius = 14
button.clipsToBounds = true
}
public func setEnabled(_ isEnabled: Bool) {
button.isEnabled = isEnabled
}
public func addTarget(target: Any,
selector: Selector) {
button.addTarget(target, action: selector, for: .touchUpInside)
}
public func setPressedBlock(_ pressedBlock: @escaping () -> Void) {
guard self.pressedBlock == nil else { return }
self.pressedBlock = pressedBlock
}
@objc
private func buttonPressed() {
pressedBlock?()
}
public func enableMultilineLabel() {
button.titleLabel?.numberOfLines = 0
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center
}
public var font: UIFont? {
return button.titleLabel?.font
}
public func autoSetHeightUsingFont(extraVerticalInsets: CGFloat = 0) {
guard let font = font else {
owsFailDebug("Missing button font.")
return
}
autoSetDimension(.height, toSize: Self.heightForFont(font) + CGFloat(extraVerticalInsets * 2.0))
}
override public var intrinsicContentSize: CGSize {
button.intrinsicContentSize
}
}
fileprivate extension CGFloat {
static var defaultCornerStyle = 5.0
static var insetCornerStyle = 14.0
}