Shaula Blog

美丽的东西都是肤浅的

iOS UIButtonConfiguration

UIButtonConfiguration 是 iOS 15+ 引入的 API,它将按钮的样式、状态管理与内容组织提升到了全新高度。

为何需要 UIButtonConfiguration?

传统 UIButton 配置痛点(繁琐且易出错):

let oldButton = UIButton(type: .system)
oldButton.setTitle("Complete", for: .normal)
oldButton.setImage(UIImage(systemName: "paperplane"), for: .normal)
oldButton.tintColor = .systemBlue
oldButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
oldButton.contentEdgeInsets = UIEdgeInsets(top: 10, left: 20, bottom: 10, right: 20)
oldButton.backgroundColor = .systemGray6
oldButton.layer.cornerRadius = 8
// 还需要为每个状态重复设置...

UIButtonConfiguration 的优点

  • 状态管理智能化:自动处理 normal/highlighted/disabled 等状态
  • 布局现代化:内置 SF Symbols 与文本的间距优化
  • 动态更新:运行时轻松修改配置属性

核心功能与使用

基础配置模板

// 创建配置
var config = UIButton.Configuration.filled()

// 内容设置
config.title = "Hello"
config.subtitle = "World"
config.image = UIImage(systemName: "globe")
config.imagePlacement = .trailing  // 图片位置

// 视觉定制
config.baseBackgroundColor = .systemIndigo
config.baseForegroundColor = .white
config.cornerStyle = .capsule      // 胶囊按钮
config.buttonSize = .large         // 尺寸预设

// 边距控制
config.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 20, bottom: 10, trailing: 20)
config.imagePadding = 8

// 应用到按钮
let modernButton = UIButton(configuration: config, primaryAction: nil)

功能示例

// 动态属性更新
func startLoading() {
    var updatedConfig = button.configuration
    updatedConfig?.showsActivityIndicator = true
    updatedConfig?.title = "处理中..."
    button.configuration = updatedConfig
}

// 多状态样式管理
button.configurationUpdateHandler = { button in
    var config = button.configuration
    config?.baseBackgroundColor = button.isHighlighted ? .systemPurple : .systemIndigo
    button.configuration = config
}

// 自定义富文本标题
let attrTitle = AttributedString("Hello world", attributes: AttributeContainer([.font: UIFont.boldSystemFont(ofSize: 18)]))
config.attributedTitle = attrTitle

// 下载按钮状态切换
enum DownloadState {
    case idle, downloading, downloaded
}

func updateButton(for state: DownloadState) {
    var config = UIButton.Configuration.tinted()
    
    switch state {
    case .idle:
        config.title = "下载"
        config.image = UIImage(systemName: "arrow.down.circle")
    case .downloading:
        config.showsActivityIndicator = true
        config.title = "取消"
        config.baseBackgroundColor = .systemGray
    case .downloaded:
        config.title = "已下载"
        config.image = UIImage(systemName: "checkmark.circle.fill")
        config.baseBackgroundColor = .systemGreen
    }
    
    downloadButton.configuration = config
}

最佳实践

  1. 优先使用预设样式.filled() / .tinted() 已适配 iOS 设计规范
  2. 利用 Symbol 缩放:配合 UIImage.SymbolConfiguration 实现精细控制
config.image = UIImage(
    systemName: "wifi", 
    withConfiguration: UIImage.SymbolConfiguration(scale: .large)
)
  1. 响应式设计:在 traitCollectionDidChange 中动态调整配置
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    updateButtonConfigurationForCurrentSizeClass()
}

结论

UIButtonConfiguration 不仅大幅减少样板代码,更提供了更强的表达能力和更流畅的状态转换。尽管仅支持 iOS 15+,但在新项目或兼容性要求允许时,它已成为现代 iOS 开发的标配工具。