如何自动计算并设置UIAlertController子视图及自身高度?
我用两个UILabel嵌套UIStackView做了个自定义视图,通过addSubview()加到UIAlertController.view上替换默认标题和消息,实现特殊样式。现在没法获取Label或视图的实际高度,只能用固定值(自定义视图高度300,UIAlertController高度400),想根据两个Label的实际高度自动计算并设置这两个高度,该怎么弄?
相关代码
主控制器代码
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) let selectAction = UIAlertAction(title: "Select", style: .default) { (action) in print("selection") } let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) alertController.addAction(selectAction) alertController.addAction(cancelAction) let customView = Popover.initCustomizedView(uiViewController: alertController) alertController.view.addSubview(customView) customView.translatesAutoresizingMaskIntoConstraints = false customView.topAnchor.constraint(equalTo: alertController.view.topAnchor, constant: 10).isActive = true customView.rightAnchor.constraint(equalTo: alertController.view.rightAnchor, constant: -10).isActive = true customView.leftAnchor.constraint(equalTo: alertController.view.leftAnchor, constant: 10).isActive = true customView.heightAnchor.constraint(equalToConstant: 300).isActive = true alertController.view.translatesAutoresizingMaskIntoConstraints = false alertController.view.heightAnchor.constraint(equalToConstant: 400).isActive = true customView.backgroundColor = .green showAlert(actionSheetAlertController: alertController)
自定义视图创建函数
static func initCustomizedView(uiViewController: UIAlertController) -> UIView{ // 创建标题标签 let titleLabel = UILabel() titleLabel.translatesAutoresizingMaskIntoConstraints = false titleLabel.text = "Custom Title bbbbbbbbbbb" titleLabel.font = UIFont.boldSystemFont(ofSize: 40) titleLabel.textColor = .brown titleLabel.textAlignment = .center titleLabel.numberOfLines = 0 // 允许多行 // 创建消息标签 let messageLabel = UILabel() messageLabel.translatesAutoresizingMaskIntoConstraints = false messageLabel.text = "Custom Message bbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccc" messageLabel.font = UIFont.systemFont(ofSize: 30) messageLabel.textColor = .yellow messageLabel.textAlignment = .right messageLabel.numberOfLines = 0 // 允许多行 // 将标签添加到自定义视图 let stackView = UIStackView(arrangedSubviews: [titleLabel, messageLabel]) stackView.axis = .vertical stackView.spacing = 10 // Add spacing between labels stackView.alignment = .fill stackView.distribution = .equalSpacing let containerView = UIView() containerView.addSubview(stackView) stackView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ stackView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), stackView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), stackView.topAnchor.constraint(equalTo: containerView.topAnchor), stackView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor) ]) containerView.layoutIfNeeded() containerView.backgroundColor = .green return containerView }
1. 移除固定高度约束,添加底部关联
删除自定义视图的固定高度约束,同时给自定义视图添加底部约束,让它和AlertController的布局边距底部建立关联,让AutoLayout自动根据内容撑开高度:
alertController.view.addSubview(customView) customView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ customView.topAnchor.constraint(equalTo: alertController.view.topAnchor, constant: 10), customView.leftAnchor.constraint(equalTo: alertController.view.leftAnchor, constant: 10), customView.rightAnchor.constraint(equalTo: alertController.view.rightAnchor, constant: -10), // 关联底部,和按钮区域保持间距 customView.bottomAnchor.constraint(equalTo: alertController.view.layoutMarginsGuide.bottomAnchor, constant: -10) ])
2. 修复自定义视图内部布局
修改StackView的分布模式为.fill,并添加内边距,确保Label内容不会紧贴边缘:
let stackView = UIStackView(arrangedSubviews: [titleLabel, messageLabel]) stackView.axis = .vertical stackView.spacing = 10 stackView.alignment = .fill stackView.distribution = .fill // 让标签根据自身内容高度分配空间 stackView.isLayoutMarginsRelativeArrangement = true stackView.layoutMargins = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) // 添内边距
同时删除自定义视图中多余的containerView.layoutIfNeeded()调用,布局会在AlertController展示时自动计算。
3. 移除AlertController的固定高度约束
删除alertController.view.heightAnchor.constraint(equalToConstant: 400).isActive = true,AlertController会根据内部自定义视图和按钮的总高度自动调整自身高度,无需手动设置。
4. 确保Label高度计算正常
两个Label已设置numberOfLines = 0,配合StackView的宽度约束,Label会自动根据内容和宽度计算所需高度,无需额外处理。
修改完成后,自定义视图会根据两个Label的实际内容高度(加上间距和内边距)自动撑开,AlertController也会自适应整体高度,完全不需要固定值。
内容的提问来源于stack exchange,提问作者William Wang

