如何让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
相关产品推荐
相关产品推荐

