UIStackView在viewDidLayoutSubviews及显隐切换时返回旧高度如何解决?
问题根本原因
- 修改
UIStackView子视图的isHidden属性后,Auto Layout不会立刻触发视图重绘,而是会等待当前Runloop周期结束后才执行布局更新,因此你在修改属性后立刻读取bounds.height拿到的是布局更新前的旧值。 - 你当前手动设置
scrollView.contentSize的逻辑不符合Auto Layout规范,系统无法自动根据stackView的大小同步滚动区域。
解决方案
1. 修正ScrollView与StackView的约束逻辑
不要手动设置contentSize,使用UIScrollView的布局引导自动计算滚动区域,代码如下:
func setupView(){ scrollView.translatesAutoresizingMaskIntoConstraints = false stackView.translatesAutoresizingMaskIntoConstraints = false // scrollView 约束到父视图 scrollView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true scrollView.backgroundColor = .white scrollView.addSubview(stackView) // stackView 约束到scrollView的content引导 stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor).isActive = true stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor).isActive = true stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor).isActive = true stackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor).isActive = true // stackView宽度和scrollView可视区域宽度一致 stackView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor).isActive = true stackView.setArrangedSubviews(views: [label1, label2, label3, label4, ..., labeln]) [label1, label2, label3].forEach { $0.isHidden = true } }
2. 强制触发布局更新后读取高度
修改子视图隐藏状态后,调用layoutIfNeeded()强制触发立即布局,就能拿到最新的高度:
func onHitButton(){ let targetLabels = [label1, label2, label3] targetLabels.forEach { $0.isHidden = isHidden } isHidden.toggle() // 强制触发立即布局更新 view.layoutIfNeeded() // 此时打印的就是最新高度 print(stackView.bounds.height) }
3. 优化viewDidLayoutSubviews逻辑
约束配置正确后,系统会自动同步scrollView.contentSize,不需要你手动修改。如果需要在布局完成后执行自定义逻辑,可以直接在viewDidLayoutSubviews里操作,此时读取的stackView.bounds已经是最新值,注意避免重复执行冗余操作即可。
内容的提问来源于stack exchange,提问作者bao le
相关产品推荐
相关产品推荐

