设备旋转后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
相关产品推荐
相关产品推荐

