如何在Swift中设置自定义视图的内在内容大小?

53

背景

我正在制作一个垂直标签,用于传统的蒙古文。以前我只是旋转一个 UILabel ,但这种方法存在一些性能问题和其他复杂性。现在我正在尝试从头开始制作标签。然而,我需要让垂直标签告诉自动布局当它的高度根据字符串长度调整时。

我所阅读的内容

我阅读了内在内容大小具有内在内容大小的视图文档。虽然这些文档更多地介绍如何使用它,但并没有介绍如何在自定义视图中定义它。

在 Stack Overflow 上搜索“ios 内在内容大小自定义视图”仅给出

这个问题甚至不需要内在内容大小,因为他们的视图只是标准视图组合而成。

我正在尝试什么

我的回答如下。我添加了这个 Q&A 对,以便其他人不必像我一样使用搜索关键字那么长时间才能找到答案。

2个回答

101

设置自定义视图的固有内容大小可以让自动布局知道该视图希望的大小。为了设置它,您需要覆盖intrinsicContentSize

override var intrinsicContentSize: CGSize {
   return CGSize(width: x, height: y)
}

然后调用

invalidateIntrinsicContentSize()

每当您的自定义视图的内在内容大小发生更改并且框架应更新时。


对我来说,添加@IBDesignable是必要的,以便让Xcode尊重内容大小。 - Balázs Vincze

17

一个具有固有高度的“视图”的示例...

@IBDesignable class HView: UIView {

    @IBInspectable var height: CGFloat = 100.0

    override var intrinsicContentSize: CGSize {
        return CGSize(width: 99, height: height)
        // if using in, say, a vertical stack view, the width is ignored
    }

    override func prepareForInterfaceBuilder() {
         invalidateIntrinsicContentSize()
    }
}

图片描述在此处输入

你可以将其设置为可检查的。

图片描述在此处输入

因为它具有内在高度,所以可以立即在代码中插入堆栈视图:

stack?.insertArrangedSubview(HView(), at: 3)

相反,如果这是一个没有内在高度的普通视图,则必须添加高度锚定或它将崩溃:

let v:UIView = HView()
v.heightAnchor.constraint(equalToConstant: 100).isActive = true
stack?.insertArrangedSubview(v, at: 3)

请注意,在堆栈视图的重要特殊情况下:

  • 您仅设置一个锚点(对于垂直堆栈视图,是高度;对于水平堆栈视图,则是宽度)。

因此,设置内在高度非常完美,因为:

  • 内在高度确实意味着如果需要,会自动设置高度锚点。

请记住,在所有子视图的正常情况下,需要很多其他锚点。


1
我建议在重写方法中返回super.intrinsicContentSize.width作为宽度,而不是像您建议的返回一个常量。这样,在视图在堆栈视图之外使用并具有宽度约束时,该约束将得到尊重。 - Vojta Böhm
嗨@VojtaBöhm - 当然可以,但这里的教学方法是要解释,在实际布局中忽略了宽度值时(例如堆栈视图中),宽度值会被忽略。 - Fattie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接