Background
I am making a vertical label to use with traditional Mongolian script. Before I was just rotating a UILabel
but there were some performance issues and other complications with this. Now I am working on making a label from scratch. However, I need the vertical label to tell auto layout when its height adjusts (based on string length).
What I have read
I read the Intrinsic Content Size and Views with Intrinsic Content Size documentation. These were more about how to use it, though, and not how to define it in a custom view.
Searching for "ios intrinsic content size for a custom view" only gives me
in Stack Overflow. This particular question didn't even need intrinsic content size because their view was just an assembly of standard views.
What I am trying
What I am trying is my answer below. I am adding this Q&A pair so that it won't take other people as long to find the answer as it took me with the search keywords that I used.
In general, the intrinsic content size simplifies the layout, reducing the number of constraints you need. However, using the intrinsic content size often requires setting the view's content-hugging and compression-resistance (CHCR) priorities, which can add additional complications.
Most views have an intrinsic content size, which refers to the amount of space the view needs for its content to appear in an ideal state. For example, the intrinsic content size of a UILabel will be the size of the text it contains using whatever font you have configured it to use.
Intrinsic content size is information that a view has about how big it should be based on what it displays. For example, a label's intrinsic content size is based on how much text it is displaying. In your case, the image view's intrinsic content size is the size of the image that you selected.
Each of the elements has it's own intrinsicContentSize so it should be possible for the UIStackView to provide its own intrinsicContentSize . The documentation states that the spacing is used as a minimum spacing. The intrinsicContentSize.
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
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 ...
so, setting the intrinsic height works perfectly, since:
Remembering that in all normal cases of a subview, many other anchors are needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With