How to set a custom view's intrinsic content size in Swift?
Setting the intrinsic content size of a custom view lets auto layout know how big that view would like to be. In order to set it, you need to override intrinsicContentSize
.
override var intrinsicContentSize: CGSize {
return CGSize(width: x, height: y)
}
Then call
invalidateIntrinsicContentSize()
Whenever your custom view's intrinsic content size changes and the frame should be updated.
Notes
- Swift 3 update: Easier Auto Layout: Coding Constraints in iOS 9
- Just because you have the intrinsic content size set up in your custom view doesn't mean it will work as you expect. Read the documentation for how to use it, paying special attention to Content-Hugging and Compression-Resistance.
- Thanks also to this Q&A for putting me on the right track: How can I add padding to the intrinsic content size of UILabel?
- Thanks also to this article and the documentation for help with
invalidateIntrinsicContentSize()
.
Example of a "view with intrinsic height" ...
@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()
}
}
which you can set as an inspectable
Since it has an intrinsic height, it can (for example) be immediately inserted in a stack view in code:
stack?.insertArrangedSubview(HView(), at: 3)
In contrast, if it was a normal view with no intrinsic height, you'd have to add a height anchor or it would crash:
let v:UIView = HView()
v.heightAnchor.constraint(equalToConstant: 100).isActive = true
stack?.insertArrangedSubview(v, at: 3)
Note that in ...
the important special case of a stack view:
- you set only ONE anchor (for vertical stack view, the height; for horizontal the width)
so, setting the intrinsic height works perfectly, since:
- the intrinsic height indeed means that the height anchor specifically will be set automatically if needed.
Remembering that in all normal cases of a subview, many other anchors are needed.