使用UIButton.Configuration创建按钮时UIStackView的.fill布局失效问题
问题描述
当子视图是通过UIButton.Configuration创建的UIButton时,UIStackView的.fill布局分布无法正常生效。
我们创建了两个配置完全一致的UIStackView,仅子视图UIButton的创建方式不同:
let stackView1 = UIStackView() stackView1.translatesAutoresizingMaskIntoConstraints = false stackView1.distribution = .fill
- 使用常规构造器创建UIButton时,
.fill布局可正常生效(对应附图中上方的栈视图):let button = UIButton() - 通过
UIButton.Configuration构造器创建UIButton时,父UIStackView无法应用正确的.fill布局(对应附图中下方的栈视图):var configuration = UIButton.Configuration.plain() let button = UIButton(configuration: configuration)
完整测试代码:
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let stackView1 = UIStackView() stackView1.translatesAutoresizingMaskIntoConstraints = false stackView1.distribution = .fill stackView1.alignment = .fill let stackView2 = UIStackView() stackView2.translatesAutoresizingMaskIntoConstraints = false stackView2.distribution = .fill stackView2.alignment = .fill view.addSubview(stackView1) view.centerXAnchor.constraint(equalTo: stackView1.centerXAnchor).isActive = true view.centerYAnchor.constraint(equalTo: stackView1.centerYAnchor).isActive = true view.addSubview(stackView2) view.centerXAnchor.constraint(equalTo: stackView2.centerXAnchor).isActive = true stackView2.topAnchor.constraint(equalTo: stackView1.bottomAnchor, constant: 40).isActive = true stackView1.addArrangedSubview(makeButton("Button", backgroundColor: .red)) stackView1.addArrangedSubview(makeButton("Button Very Wild!!", backgroundColor: .blue)) stackView1.addArrangedSubview(makeButton("Button mid size", backgroundColor: .yellow)) stackView1.addArrangedSubview(makeButton("But", backgroundColor: .cyan)) stackView2.addArrangedSubview(makeButtonWithConfiguration("Button", backgroundColor: .red)) stackView2.addArrangedSubview(makeButtonWithConfiguration("Button Very Wild!!", backgroundColor: .blue)) stackView2.addArrangedSubview(makeButtonWithConfiguration("Button mid size", backgroundColor: .yellow)) stackView2.addArrangedSubview(makeButtonWithConfiguration("But", backgroundColor: .cyan)) } func makeButton(_ title: String, backgroundColor: UIColor) -> UIButton { let button = UIButton() button.setTitle(title, for: .normal) button.backgroundColor = backgroundColor return button } func makeButtonWithConfiguration(_ title: String, backgroundColor: UIColor) -> UIButton { var configuration = UIButton.Configuration.filled() configuration.title = title configuration.baseBackgroundColor = backgroundColor let button = UIButton(configuration: configuration) return button } }
环境:XCode 15.4,iOS 17.5模拟器
问题原因
通过UIButton.Configuration创建的按钮,默认带有较高的内容压缩抵抗优先级和内容拥抱优先级,这两个优先级会阻止UIStackView的.fill布局对按钮进行拉伸。而常规UIButton的这些优先级默认值较低,因此能被栈视图正常拉伸填充。
解决方法
方法1:调整按钮的优先级
在创建Configuration按钮后,手动修改其水平方向的优先级,允许栈视图对按钮进行拉伸和压缩:
func makeButtonWithConfiguration(_ title: String, backgroundColor: UIColor) -> UIButton { var configuration = UIButton.Configuration.filled() configuration.title = title configuration.baseBackgroundColor = backgroundColor let button = UIButton(configuration: configuration) // 降低水平内容压缩抵抗优先级,允许按钮被压缩 button.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) // 降低水平内容拥抱优先级,允许按钮被拉伸 button.setContentHuggingPriority(.defaultLow, for: .horizontal) return button }
方法2:清除Configuration的尺寸约束
直接通过Configuration的sizeConstraints属性移除按钮的固有尺寸约束,让栈视图完全控制按钮尺寸:
func makeButtonWithConfiguration(_ title: String, backgroundColor: UIColor) -> UIButton { var configuration = UIButton.Configuration.filled() configuration.title = title configuration.baseBackgroundColor = backgroundColor // 清除固有尺寸约束,交由栈视图管理尺寸 configuration.sizeConstraints = nil let button = UIButton(configuration: configuration) return button }
内容的提问来源于stack exchange,提问作者Petro Shm
相关产品推荐
相关产品推荐

