如何正确使用 UIView systemLayoutSizeFitting 获取使用给定宽度显示所有子视图的高度?

How to corrently use UIViews systemLayoutSizeFitting to get the height to show all subviews using a given width?

TD;DR

似乎在某些情况下 systemLayoutSizeFitting 没有 return 正确的高度来正确显示/定位一个视图的所有子视图。我使用 systemLayoutSizeFitting 是错误的还是有其他方法可以避免这种情况?


长话短说:

UIViewController 的 XIB 文件不仅包含主视图,还包含一些在运行时添加到视图控制器视图的其他视图。所有这些额外的视图在添加到视图控制器视图时应该获得相同的高度。

视图可能如下所示:一个简单的容器视图,其中包含一些相互堆叠的子视图。

由于容器视图的高度应该是灵活的,底部按钮和它上面的标签之间的垂直间距,使用了grater-than约束.

为了让所有视图具有相同的高度,我尝试使用 systemLayoutSizeFitting:

来测量每个视图的必要高度
@IBOutlet var pageViews: [UIView]!

override func viewDidLoad() {
    super.viewDidLoad()

    var maxHeight: CGFloat = 0
    for pageView in pageViews {
        // Add pageView somewhere on view and give it leading, trailing and top
        // constraint, but no height constraint yet.
        addToView(pageView)
        
        maxHeight = max(maxHeight, pageView.systemLayoutSizeFitting(CGSize(width: view.frame.width, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel).height)
    }
    
    for pageView in pageViews {
        // Give all pageViews the same height
        pageView.heightAnchor.constraint(equalToConstant: maxHeight).isActive = true
    }
}

这不起作用,当标签文本变得很长时:

右例中高度不够大,因此按钮被挤压。我可以通过提高按钮的垂直压缩阻力来解决这个问题,但是在这种情况下,其他控件(例如标题标签)被挤压...

这是为什么?为什么不 systemLayoutSizeFitting return 一个足以显示所有控件而无需任何挤压的高度?

如果您希望您的视图抵抗压缩,您应该使用 defaultHigh 优先级作为 verticalFittingPriority 而不是 fittingSizeLevel

当标签文本变大时,它实际上会粉碎 button's height。您正在设置顶部和底部约束,但未声明按钮高度,因此当标签变大时,视图基本上说“我可以在更新高度之前降低按钮高度,我有 space.Bottom 并且顶部约束仍然相同,没有效果。

给按钮 constant height 约束可能会解决您的问题。