Resizing a UIView subclass with dynamic sized subviews
I currently have a UIView subclass that acts as my header view for my UITableViewController. All of the subviews vary in size depending on data retrieved for a particular item.
layoutSubViews is getting called for the UIView before I can determine the size of each label. This causes a problem because I set the size of the view within the layoutSubViews method. Since it gets called before I setup my labels, the views height is always 0. Even after setting开发者_如何学编程 up the labels I call setNeedsLayout but the table views header size does not change.
This will create my TableHeaderView and set the text for my labels.
TableHeaderView *tableHeaderView = [[TableHeaderView alloc] initWithFrame:CGRectZero];
tableHeaderView.headerTitle.text = title;
tableHeaderView.headerOption1.text = headerOption1
tableHeaderView.headerOption2.text = headerOption2
tableHeaderView.headerOption3.text = headerOption3
[[self tableView] setTableHeaderView:tableHeaderView];
[tableHeaderView setNeedsLayout];
[tableHeaderView release];
Here is my UIView subclass
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
UIView *headerView = self;
self.headerTitle = [[UILabel alloc] initWithFrame:CGRectZero];
self.headerTitle.numberOfLines = 3;
self.headerTitle.lineBreakMode = UILineBreakModeWordWrap;
[headerView addSubview:self.headerTitle];
[self.headerTitle release];
self.headerOption1 = [[UILabel alloc] initWithFrame:CGRectZero];
self.headerOption1.numberOfLines = 2;
self.headerOption1.lineBreakMode = UILineBreakModeWordWrap;
[headerView addSubview:self.headerOption1];
[self.headerOption1 release];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGSize maxLabelSize;
/*...*/
[self.headerTitle setFrame:CGRectMake(10.0f, 10.0f, titleWidth, titleHeight)];
/*...*/
[self.headerOption1 setFrame:CGRectMake(10.0f, (self.headerTitle.frame.origin.y + self.headerTitle.bounds.size.height + 2.5f), pubWidth, pubHeight)];
/*...*/
[self setFrame:CGRectMake(0.0f, 0.0f, 320.0f, tableHeaderHeight)];
}
The second time that layoutSubViews is called all of the subviews get sized correctly except for the view itself (tableHeaderHeight has the correct height). Should I not be resizing the view from this method? Is there a better approach to this?
You likely need to override sizeThatFits:
on your UIView subclass to return the appropriate size based on your layout.
Use it like this:
TableHeaderView *tableHeaderView = [[TableHeaderView alloc] initWithFrame:CGRectZero];
tableHeaderView.headerTitle.text = title;
tableHeaderView.headerOption1.text = headerOption1
tableHeaderView.headerOption2.text = headerOption2
tableHeaderView.headerOption3.text = headerOption3
tableHeaderView.frame = (CGRect){
.origin = tableHeaderView.frame.origin,
.size = [tableHeaderView sizeThatFits:CGSizeZero],
};
[[self tableView] setTableHeaderView:tableHeaderView];
[tableHeaderView setNeedsLayout]; // I don't think you need this anymore.
[tableHeaderView release];
If I replace
[tableHeaderView setNeedsLayout];
with
[tableHeaderView layoutSubviews];
the header view is sized correctly. This is happening because setNeedsLayout does not call layoutSubViews until after the view has been set to the header view. If i directly call layoutSubViews however, layoutSubviews will be called before setting the view.
But I have heard in the past that directly calling layoutSubviews is not a good idea, is that also true for this case?
精彩评论