swift版 按钮图片左右上下布局+中间距离
2021-03-16 本文已影响0人
授之以渔不如授之以鱼
image.png
意思大家都懂,码来!
import UIKit
extension UIButton {
/// 按钮布局样式
public enum ButtonLayoutStyle {
case none, leftImageRightText, rightImageLeftText, topImageBottomText
}
fileprivate struct AssociatedKeys {
static var imageTextSpacing: CGFloat = 0.0
static var layoutStyle: ButtonLayoutStyle = .none
}
/// 布局样式
public var layoutStyle: ButtonLayoutStyle {
get {
guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.layoutStyle) as? ButtonLayoutStyle else {
return .none
}
return obj
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.layoutStyle, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
/// 间隙
public var imageTextSpacing: CGFloat {
get {
guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.imageTextSpacing) as? CGFloat else { return 0 }
return obj
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.imageTextSpacing, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
/// 计算内部大小(宽高自适应)
/// 参考:https://github.com/DataDesignSystems/lavoro/blob/02b3090c298c2b4cbea352d9d1adae73eb8022c3/Lavoro/Helpers/UIButton%2BExts.swift
/// 参考:[关于 UIButton 的 titleEdgeInsets、imageEdgeInsets 及 contentEdgeInsets](https://www.jianshu.com/p/2f0e9150a2a3)
override open var intrinsicContentSize: CGSize {
let intrinsicContentSize = super.intrinsicContentSize
guard self.layoutStyle != .none else {
return intrinsicContentSize
}
// 调整边距
self.adjustInsets()
// 调整宽度
let spacing = self.imageTextSpacing
var contentWidth = intrinsicContentSize.width
var contentHeight = intrinsicContentSize.height
switch self.layoutStyle {
case .leftImageRightText:
contentWidth += spacing
contentHeight += (titleEdgeInsets.top - titleEdgeInsets.bottom)
break
case .rightImageLeftText:
contentWidth += spacing
contentHeight += (titleEdgeInsets.top - titleEdgeInsets.bottom)
break
case .topImageBottomText:
contentHeight += spacing
contentHeight += (titleEdgeInsets.top + abs(imageEdgeInsets.top)) // 追加撑大高度
break
default:
break
}
// 返回内部大小
return CGSize(width: contentWidth, height: contentHeight)
}
/// 调整边距 参考:https://github.com/Jyhwenchai/UIButton
func adjustInsets() {
// Use predefined font, otherwise use the default
let text = titleLabel?.text ?? ""
let font: UIFont = titleLabel?.font ?? UIFont()
let textSize: CGSize = text.size(withAttributes: [NSAttributedString.Key.font: font])
let imageSize: CGSize = self.imageRect(forContentRect: frame).size
let spacing = self.imageTextSpacing
let offset = spacing / 2.0
switch self.layoutStyle {
case .leftImageRightText: // ---|--- 文字右移,图片左移
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: offset, bottom: 0, right: -offset)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: -offset, bottom: 0, right: offset)
break
case .rightImageLeftText: // ---|--- 文字左移,图片右移
let titleHOffset = imageSize.width
let imageHOffset = textSize.width
// 1) 左右布局
let titleInsets = UIEdgeInsets(top: 0, left: -titleHOffset, bottom: 0, right: titleHOffset)
let imageInsets = UIEdgeInsets(top: 0, left: imageHOffset, bottom: 0, right: -imageHOffset)
// 2) 追加间隔
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: titleInsets.left - offset, bottom: 0, right: titleInsets.right + offset)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: imageInsets.left + offset, bottom: 0, right: imageInsets.right - offset)
break
case .topImageBottomText: // 文字下移,图片上移
let titleHOffset = imageSize.width / 2.0
let imageHOffset = textSize.width / 2.0
let titleVOffset = imageSize.height / 2.0
let imageVOffset = textSize.height / 2.0
// 1) 上下布局
let titleInsets = UIEdgeInsets(top: titleVOffset, left: -titleHOffset, bottom: -titleVOffset, right: titleHOffset)
let imageInsets = UIEdgeInsets(top: -imageVOffset, left: imageHOffset, bottom: imageVOffset, right: -imageHOffset)
// 2) 追加间隔
self.titleEdgeInsets = UIEdgeInsets(top: titleInsets.top + offset, left: titleInsets.left, bottom: titleInsets.bottom - offset, right: titleInsets.right)
self.imageEdgeInsets = UIEdgeInsets(top: imageInsets.top - offset, left: imageInsets.left, bottom: imageInsets.bottom + offset, right: imageInsets.right)
break
default:
break
}
}
}