直接上代码,看注释
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.addTarget(self, action: #selector(filterConditionSelectAction(btn:)), for: .touchUpInside)
if #available(iOS 15.0, *) {
// 初始化一个configuration,有多种方法,可根据需要选择
btn.configuration = UIButton.Configuration.plain()
// title 和 subtitle的对其关系,文本是上下排版的
btn.configuration?.titleAlignment = .leading
// title he subtitle的间距
btn.configuration?.titlePadding = 16.scaleToScreen()
// image 和 文本 的相对位置
btn.configuration?.imagePlacement = .trailing
// image 和 文本的间距
btn.configuration?.imagePadding = 16.scaleToScreen()
// button的内容(title,subtitle,image)显示后与按钮的边距,默认由一段距离
btn.configuration?.contentInsets = NSDirectionalEdgeInsets.zero
// 设置按钮的状态变化的监听,根据变化来改变按钮的显示内容,之前都是全部设置进去自动切换的,现在不行了
btn.configurationUpdateHandler = {(button: UIButton) -> Void in
//根据状态修改内容
switch button.state {
case .normal, .highlighted:
// image变化
button.configuration?.image = UIImage.arrowPickUp
// 背景的变化,默认会有些自带效果,
button.configuration?.background.backgroundColor = .clear
// 字体的样式与之前一样
button.configuration?.attributedTitle = AttributedString(title, attributes: AttributeContainer([
NSAttributedString.Key.font : UIFont.customMediumFont(ofSize: UIFont.sizeL),
NSAttributedString.Key.foregroundColor : UIColor.whiteAlpha50 ?? .red]))
// 子标题,iOS15之后才有,对应的button.subtitleLabel
button.configuration?.subtitle = "abc"
case .selected, [.selected, .highlighted]:
// image变化,与上面对应
button.configuration?.image = UIImage.arrowUnfold
case .disabled:
Log.Debug(message: "不可\(btn.state)")
default:
Log.Debug(message: "默认值\(btn.state)")
}
button.updateConfiguration()
}
} else {
// iOS15 之前的属性设置
btn.setTitle(title, for: .normal)
// 字体颜色
btn.setTitleColor(UIColor.whiteAlpha50, for: .normal)
btn.setTitleColor(UIColor.whiteAlpha50, for: .selected)
// 设置图片各种状态都需要设置
btn.setImage(UIImage.arrowUnfold, for: .normal)
btn.setImage(UIImage.arrowUnfold, for: .highlighted)
btn.setImage(UIImage.arrowPickUp, for: .selected)
btn.setImage(UIImage.arrowPickUp, for: [.selected, .highlighted])
btn.titleLabel?.font = UIFont.customFont(ofSize: UIFont.sizeL)
// 改变title与image的位置关系
btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -15.scaleToScreen(), bottom: 0, right: 15.scaleToScreen())
btn.imageEdgeInsets = UIEdgeInsets(top: 0, left: 51.scaleToScreen(), bottom: 0, right: -51.scaleToScreen())
btn.backgroundColor = .gray
}
view.addSubview(btn)
按钮的内部布局控制比之前简单很多,不像之前,简单的 可以通过titleEdgeInsets 和 imageEdgeInsets来处理,复杂的就需要自定了,
自定义demo
import UIKit
public enum CustomButtonLayoutType : Int {
case system
case imageTop
case imageRight
case avatar
}
public class CustomButton: UIButton {
public var cusFont: UIFont? {
get {
return self.titleLabel?.font
}
set {
self.titleLabel?.font = newValue
}
}
public var layoutType: CustomButtonLayoutType = .system
override public func titleRect(forContentRect contentRect: CGRect) -> CGRect {
if layoutType == .system || contentRect == CGRect.zero {
return super.titleRect(forContentRect: contentRect)
}
let imageSize = super.imageRect(forContentRect: contentRect)
let titleSize = calculateTitleSize(size: contentRect.size)
switch layoutType {
case .imageTop:
let x = (contentRect.width - titleSize.width) / 2 + contentRect.minX + self.titleEdgeInsets.left
let y = (contentRect.height + imageSize.height - titleSize.height) / 2 + contentRect.minY + self.titleEdgeInsets.top
return CGRect(x: x, y: y, width: titleSize.width, height: titleSize.height)
case .imageRight:
let x = (contentRect.width - imageSize.width - titleSize.width) / 2 + contentRect.minX + self.titleEdgeInsets.left
let y = (contentRect.height - titleSize.height) / 2 + contentRect.minY + self.titleEdgeInsets.top
return CGRect(x: x, y: y, width: titleSize.width, height: titleSize.height)
default:
return super.titleRect(forContentRect: contentRect)
}
}
override public func imageRect(forContentRect contentRect: CGRect) -> CGRect {
if layoutType == .system || contentRect == CGRect.zero{
return super.imageRect(forContentRect: contentRect)
}
let imageSize = super.imageRect(forContentRect: contentRect)
let titleSize = calculateTitleSize(size: contentRect.size)
switch layoutType {
case .imageTop:
let x = (contentRect.width - imageSize.width) / 2 + contentRect.minX + self.imageEdgeInsets.left
let y = (contentRect.height - imageSize.height - titleSize.height) / 2 + contentRect.minY + self.imageEdgeInsets.top
return CGRect(x: x, y: y, width: imageSize.width, height: imageSize.height)
case .imageRight:
let x = (contentRect.width + titleSize.width - imageSize.width) / 2 + contentRect.minX + self.imageEdgeInsets.left
let y = (contentRect.height - imageSize.height) / 2 + contentRect.minY + self.imageEdgeInsets.top
return CGRect(x: x, y: y, width: imageSize.width, height: imageSize.height)
case .avatar:
let bgImageWidth: CGFloat = self.currentBackgroundImage?.size.width ?? imageSize.width
let width: CGFloat = imageSize.width * contentRect.width / bgImageWidth
let height = width * imageSize.height / imageSize.width
let x = (contentRect.width - width) + contentRect.minX + self.imageEdgeInsets.left
let y = (contentRect.height - height) + contentRect.minY + self.imageEdgeInsets.top
return CGRect(x: x, y: y, width: width, height: height)
default:
return super.imageRect(forContentRect: contentRect)
}
}
override public func backgroundRect(forBounds bounds: CGRect) -> CGRect {
return super.backgroundRect(forBounds: bounds)
}
private func calculateTitleSize(size: CGSize) -> CGSize {
if let title = self.currentAttributedTitle {
return title.size()
}
if let title = self.currentTitle {
let options: NSStringDrawingOptions = .usesLineFragmentOrigin
let attributes : [NSAttributedString.Key : Any] = [.font: cusFont ?? UIFont.customFont(ofSize: UIFont.size1xl)]
return title.boundingRect(with: size, options: options, attributes: attributes, context: nil).size
}
return CGSize.zero
}
}
网友评论