Given a view hierarchy that looks something like this:
ContainerView
UIScrollView
ModuleView
ModuleView
ModuleView
...
I'd like the ContainerView
to lay the ModuleViews
out in some arbitrary fashion (list, grid etc.). To do this, I'd implement -[ContainerView layoutSubviews]
which would iterate through the ModuleViews
, call -[ModuleView sizeToFit]
on each one, and then position them relative to one another according to the desired layout.
My question is to do with the best way of implementing -[ModuleView sizeThatFits:]
and -[ModuleView layoutSubviews]
to minimise repetition and to allow ModuleViews
to change size while maintaining the layout correctly.
Take the simplest case where ModuleView
is a UIView
with a multi-line UILabel
subview, and padding on either side. It might look something like this:
@implementation ModuleView
- (CGSize)sizeThatFits:(CGSize)size {
CGFloat padding = 10.0f;
CGSize labelMaxSize = CGSizeMake(superview.size.width - (2 * padding), CGFLOAT_MAX);
CGSize labelSize = [self.label.text sizeWithFont:self.label.font constrainedToSize:labelMaxSize lineBreakMode:self.label.lineBreakMode];
return CGSizeMake(superview.width, labelSize.height + (2 * padding));
}
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat padding = 10.0f;
CGSize labelMaxSize = CGSizeMake(self.size.width - (2 * padding), CGFLOAT_MAX);
CGSize labelSize = [self.label.text sizeWithFont:self.label.font constrainedToSize:labelMaxSize lineBreakMode:self.label.lineBreakMode];
self.label.frame = CGRectMake(padding, padding, labelSize.width, labelSize.height);
CGRect frame = self.frame;
frame.size.height = self.label.frame.size.height + (2 * padding);
self.frame = frame;
}
@end
As you can see, the size of the subviews is calculated once in sizeThatFits:
, and again in layoutSubviews
. This works, but quickly becomes a mess when the views are more complicated.
Is there a way to simplify this? I haven't been able to find good examples of how others approach this problem.