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

设备旋转后Container View内自适应TableView高度异常问题

问题描述

在Container View(绿色视图)中嵌入了包含自适应TableView的ViewController。横屏切换时UI显示正常,但切回竖屏后,Container View内紫色背景的TableView高度无法更新。已尝试在viewWillTransition方法中调用view.setNeedsLayout()、containerView.setNeedsLayout()、view.layoutIfNeeded(),问题仍未解决。

补充代码

向Container View添加子视图的代码

func showMCQs() {
    mcqKit = MCQKit()
    mcqKit!.configureMCQV2()
    addChild(MCQKit.mcqV2Controller)
    containerView.addSubview(MCQKit.mcqV2Controller.view)
    MCQKit.mcqV2Controller.didMove(toParent: self)
    MCQKit.mcqV2Controller.view.anchor(top: containerView.topAnchor, left: containerView.leftAnchor, bottom: containerView.bottomAnchor, right: containerView.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: nil, height: nil, centerX: nil, centerY: nil)
}

extension UIView {
func anchor(top: NSLayoutYAxisAnchor?, left: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, right: NSLayoutXAxisAnchor?,  paddingTop: CGFloat?, paddingLeft: CGFloat?, paddingBottom: CGFloat?, paddingRight: CGFloat?, width: CGFloat?, height: CGFloat?, centerX: NSLayoutXAxisAnchor?, centerY: NSLayoutYAxisAnchor?) {
    translatesAutoresizingMaskIntoConstraints = false
    
    if let safeTop = top, let safePaddingTop = paddingTop {
        topAnchor.constraint(equalTo: safeTop, constant: safePaddingTop).isActive = true
    }
    
    if let safeLeft = left, let safePaddingLeft = paddingLeft {
        leftAnchor.constraint(equalTo: safeLeft, constant: safePaddingLeft).isActive = true
    }
    
    if let safeBottom = bottom, let safePaddingBottom = paddingBottom  {
        bottomAnchor.constraint(equalTo: safeBottom, constant: -safePaddingBottom).isActive = true
    }
    
    if let safeRight = right, let safePaddingRight = paddingRight  {
        rightAnchor.constraint(equalTo: safeRight, constant: -safePaddingRight).isActive = true
    }
    
    if let safeWidth = width, safeWidth != 0 {
        widthAnchor.constraint(equalToConstant: safeWidth).isActive = true
    }
    
    if let safeHeight = height, safeHeight != 0{
        heightAnchor.constraint(equalToConstant: safeHeight).isActive = true
    }
    
    if let centerX = centerX {
        centerXAnchor.constraint(equalTo: centerX).isActive = true
    }
    
    if let centerY = centerY {
        centerYAnchor.constraint(equalTo: centerY).isActive = true
    }
}

自适应TableView代码

class CustomTableView: UITableView {

// Self sizing tableView
override public func layoutSubviews() {
    super.layoutSubviews()
    if bounds.size != intrinsicContentSize {
        invalidateIntrinsicContentSize()
    }
}

override public var intrinsicContentSize: CGSize {
    layoutIfNeeded()
    return contentSize
}
解决方案

1. 在旋转过渡中主动触发TableView尺寸更新

修改viewWillTransition方法,在过渡动画中强制刷新TableView并更新内在尺寸:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    
    coordinator.animate(alongsideTransition: { _ in
        // 替换成你的内嵌ViewController类型
        guard let mcqVC = MCQKit.mcqV2Controller as? YourMCQViewController,
              let tableView = mcqVC.view.subviews.first(where: { $0 is CustomTableView }) as? CustomTableView else {
            return
        }
        
        tableView.reloadData() // 确保行高随屏幕宽度重新计算
        tableView.invalidateIntrinsicContentSize()
        tableView.layoutIfNeeded()
        
        self.containerView.setNeedsLayout()
        self.containerView.layoutIfNeeded()
    }, completion: nil)
}

2. 优化CustomTableView的自适应逻辑

原代码中仅在bounds与intrinsicContentSize不一致时才更新,可能导致旋转时遗漏触发。修改为每次布局都刷新内在尺寸:

class CustomTableView: UITableView {
    override public func layoutSubviews() {
        super.layoutSubviews()
        // 每次布局都主动刷新内在尺寸
        invalidateIntrinsicContentSize()
    }
    
    override public var intrinsicContentSize: CGSize {
        layoutIfNeeded()
        // 避免contentSize高度为0导致的布局异常
        let safeHeight = max(contentSize.height, 1)
        return CGSize(width: contentSize.width, height: safeHeight)
    }
}

3. 检查内嵌ViewController的布局约束

确保mcqV2Controller中的CustomTableView是通过约束绑定到父view的四边,没有设置固定高度约束。同时确认mcqV2Controller的view没有额外的高度限制(当前anchor方法已经绑定四边,这部分无需修改)。

4. 在viewDidLayoutSubviews中补充更新

如果旋转后仍有延迟,可在父ViewController的viewDidLayoutSubviews中再次触发TableView尺寸更新:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    guard let mcqVC = MCQKit.mcqV2Controller,
          let tableView = mcqVC.view.subviews.first(where: { $0 is CustomTableView }) as? CustomTableView else {
        return
    }
    
    tableView.invalidateIntrinsicContentSize()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 18:51:17