To answer your question: Could someone please point me in the right direction to control the relative widths of stacks nested inside other stacks?
...
The problem is that your top-level UIStackView
is asking for the intrinsicContentSize
of all its subviews when determining how to divy up extra space/squash things together, based on each of the subviews' returned intrinsicContentSize
and their contentHuggingPriority/contentCompressionResistance. Unfortunately, UIStackView
itself - ie your nested UIStackView
- doesn't return anything useful for its own intrinsicContentSize
(despite it having its own subviews, which do). So the top-level UIStackView just ploughs ahead and lays things out as though the nested one doesn't care, which is why your nested UIStackView is ending up wider than you'd like.
I've had good luck by using a simple UIStackView
subclass for the nested one which returns a useful intrinsicContentSize
based on its own contents' widths (for a vertical axis) or heights (for a horizonal axis), as follows:
@implementation NestedStackView
- (CGSize)intrinsicContentSize
{
CGSize size = [super intrinsicContentSize]; // returns {UIViewNoIntrinsicMetric,UIViewNoIntrinsicMetric}
for (UIView *view in self.arrangedSubviews)
if (!view.hidden) { // UIStackView ignores hidden subviews when doing its layout; so should we...
if (self.axis == UILayoutConstraintAxisVertical) {
size.width = MAX(view.intrinsicContentSize.width, size.width);
} else {
size.height = MAX(view.intrinsicContentSize.height, size.height);
}
}
return size;
}
@end
By doing so, the top-level UIStackView now takes the nested UIStackView's desired content width into account when allocating its space. [aside: I first attempted adding an explicit NSLayoutConstraint on the width of the nested UIStackView, but it was just ignored. Whereas returning an instrinsicContentSize.width worked]