You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自动计算并设置UIAlertController子视图及自身高度?

动态计算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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 22:54:50