/// 按钮图片和标题的布局样式
/// - Cases:
/// - imageLeft: 图片在标题左侧,可设置标题左侧间距
/// - imageRight: 图片在标题右侧,可设置标题右侧间距
/// - imageTop: 图片在标题上方,可设置两者间距
/// - imageBottom: 图片在标题下方,可设置两者间距
/// - default: 默认布局(图片在左,无间距)
enum ButtonImageTitlePosition {
case imageLeft(padding: CGFloat = 0)
case imageRight(padding: CGFloat = 0)
case imageTop(padding: CGFloat)
case imageBottom(padding: CGFloat)
case `default`
}
extension UIButton {
/// 设置按钮图片和标题的布局样式
/// - Parameter position: 布局样式及间距配置
func setImageTitlePosition(_ position: ButtonImageTitlePosition) {
if #available(iOS 15.0, *) {
configureForiOS15AndAbove(position)
} else {
configureForLegacyiOS(position)
}
}
// MARK: - iOS 15+ 配置方法
@available(iOS 15.0, *)
private func configureForiOS15AndAbove(_ position: ButtonImageTitlePosition) {
// 获取或创建按钮配置(保留现有配置)
var configuration = self.configuration ?? .plain()
// 保持原有的字体样式
if let titleLabel = self.titleLabel {
let font = titleLabel.font
titleLabel.adjustsFontForContentSizeCategory = false // 防止字体自动调整
configuration.attributedTitle = AttributedString(titleLabel.text ?? "", attributes: AttributeContainer([.font: font as Any]))
// 确保字体不会被 UIButton.Configuration 修改
configuration.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { incoming in
var outgoing = incoming
outgoing.font = font
return outgoing
}
}
switch position {
case .imageLeft(let padding):
configuration.imagePlacement = .leading // 图片在前(左)
configuration.imagePadding = padding // 图片与标题间距
case .imageRight(let padding):
configuration.imagePlacement = .trailing // 图片在后(右)
configuration.imagePadding = padding
case .imageTop(let padding):
configuration.imagePlacement = .top // 图片在上
configuration.imagePadding = padding
case .imageBottom(let padding):
configuration.imagePlacement = .bottom // 图片在下
configuration.imagePadding = padding
case .default:
configuration.imagePlacement = .leading // 默认左对齐
configuration.imagePadding = 0 // 无间距
}
self.configuration = configuration
}
// MARK: - iOS 14 及以下版本配置方法
private func configureForLegacyiOS(_ position: ButtonImageTitlePosition) {
// 确保 imageView 和 titleLabel 存在
guard let imageView = self.imageView, let titleLabel = self.titleLabel else { return }
// 获取图片和标题的尺寸
let imageSize = imageView.frame.size
let titleSize = titleLabel.frame.size
let buttonSize = self.bounds.size
/// 计算水平方向上的居中偏移量
func centerXOffset(for width: CGFloat) -> CGFloat {
return (buttonSize.width - width) / 2
}
switch position {
case .imageLeft(let padding):
setEdgeInsets(imageLeft: -padding / 2, titleLeft: padding / 2)
case .imageRight(let padding):
setEdgeInsets(imageLeft: titleSize.width + padding / 2, titleLeft: -(imageSize.width + padding / 2))
case .imageTop(let padding):
let totalHeight = imageSize.height + padding + titleSize.height
setEdgeInsets(imageTop: -(buttonSize.height - totalHeight) / 2, titleTop: (buttonSize.height - totalHeight) / 2 + imageSize.height + padding)
case .imageBottom(let padding):
let totalHeight = imageSize.height + padding + titleSize.height
setEdgeInsets(imageTop: (buttonSize.height - totalHeight) / 2 + titleSize.height + padding, titleTop: -(buttonSize.height - totalHeight) / 2)
case .default:
setEdgeInsets()
}
}
/// 设置按钮的内边距(imageEdgeInsets 和 titleEdgeInsets)
/// - Parameters:
/// - imageLeft: 图片左边距调整
/// - titleLeft: 标题左边距调整
/// - imageTop: 图片上边距调整
/// - titleTop: 标题上边距调整
private func setEdgeInsets(imageLeft: CGFloat = 0, titleLeft: CGFloat = 0, imageTop: CGFloat = 0, titleTop: CGFloat = 0) {
self.imageEdgeInsets = UIEdgeInsets(top: imageTop, left: imageLeft, bottom: -imageTop, right: -imageLeft)
self.titleEdgeInsets = UIEdgeInsets(top: titleTop, left: titleLeft, bottom: -titleTop, right: -titleLeft)
}
}
UIButton 图片和标题布局扩展
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 自己随便的写的一个按钮布局图片以及文字,同时可以加载网络图片,方便简单。 github地址 demo 效果图 使用...
- 前言 之前对于那种上面是图片下面是文字的按钮都是通过一个ImageView、一个Label、一个Button实现的...