You need to enable JavaScript to run this app. 如何让UIStackView中的UITextView动态自适应内容大小
优惠活动
大模型
产品
解决方案
定价
更多

如何让UIStackView中的UITextView动态自适应内容大小

问题原因及修复方案

核心错误点

  • UIStackView的distribution属性配置错误:fillProportionally会按照子视图固有尺寸的比例分配StackView的可用高度,多子视图场景下会忽略子视图真实内容高度,导致自适应失效,单个子视图时没有其他视图分摊高度,所以看起来正常。
  • UIScrollView与StackView的约束不完整:UIScrollView的自动布局需要内容视图完整锚定四个边,同时明确内容视图的宽度/高度,你既没有给ScrollView本身加父视图约束,也没有绑定StackView的底部锚点和宽度约束,导致系统无法自动计算ScrollView的contentSize,手动赋值contentSize的方式也不可靠。
  • 手动计算intrinsicContentSize的时机错误:关闭滚动的UITextView需要先确定自身宽度,才能计算出文本对应的高度,你在宽度还未确定的layoutSubviews中读取bounds高度,自然拿到的是0值,且本身你的InfoView约束已经可以实现自撑,无需手动覆写固有尺寸。

修复步骤

1. 移除InfoView中手动计算固有尺寸的代码

你原来的InfoView约束已经满足自撑要求,直接删掉你后续添加的layoutSubviews、height属性、intrinsicContentSize覆现代码即可。

2. 修正MyViewController中的约束配置

完整修正后的代码如下:

class MyViewController: UIViewController {
    var infoModelArr: [InfoModel]!
    var stackView: UIStackView!
    var scrollView: UIScrollView!
    
    init(infoModelArr: [InfoModel]) {
        self.infoModelArr = infoModelArr
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        // 先初始化ScrollView并添加约束
        scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(scrollView)
        
        var infoViewArr = [InfoView]()
        for infoModel in infoModelArr {
            let infoView = InfoView(infoModel: infoModel)
            infoViewArr.append(infoView)
        }
        
        stackView = UIStackView(arrangedSubviews: infoViewArr)
        stackView.axis = .vertical
        stackView.spacing = 10
        // 修改distribution为fill,按子视图真实高度排列
        stackView.distribution = .fill
        stackView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(stackView)
        
        NSLayoutConstraint.activate([
            // 给ScrollView加父视图约束
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            
            // StackView锚定ScrollView的四个内容边
            stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
            stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
            stackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
            
            // 固定StackView宽度等于ScrollView的宽度,避免横向滚动
            stackView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
        ])
    }

    // 删掉手动设置contentSize的代码,AutoLayout会自动计算
}

适配说明

关闭isScrollEnabled的UITextView会自动根据内容和自身宽度计算固有高度,只要子视图的约束可以完整撑起父视图的尺寸,垂直UIStackView就会自动适配每个子视图的高度,不需要手动计算任何尺寸。

内容的提问来源于stack exchange,提问作者Kevvv

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 06:06:02