I've been struggling with this now for a little while, and I want to make sure I'm doing this the right way. For reference, I am using AutoLayout with Storyboards, and it's an iOS7-only app.
I have a UITableView with a header-view, and the UI for the HeaderView is hooked up in the storyboard. I've left the header in the storyboard, and it contains a few elements, one of which is a non-scrollable UITextView.
Here is a screenshot of how it basically looks in the storyboard:
I darkened the header-view's background to a darker grey so it stands out.
The UITextView's text can be dynamic, so its height needs to change depending on the size of the text. But the tricky part is that the table's header-view needs to adjust its height as well, depending on this text's size. I've tried a few different things with constraints, but it's not really working correctly (unless I disable AutoLayout and re-size things programatically, which I really would like to avoid).
I want this to be as clean as possible with as little code as necessary, of course. I am not tied to using the table-view header, although it works well with my needs, since I want it and its containing textview to scroll with the actual details below. But that all being said, if there is a more simple approach to accomplishing this (i.e. with a uilabel), I will gladly change the underlying structure.
Any thoughts as to an approach? Not looking for someone to hold my hand through an answer; just looking mainly for some good starting points if possible. Thanks in advance!
Some time ago I found new solution, maybe it needs tweaking for animations and is experimental, but, for some range of cases it's fine, so give it a try:
-updateTableViewHeaderViewHeight
)-resetTableViewHeaderView
)Here's some code:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self updateTableViewHeaderViewHeight];
}
/**
tableView's tableViewHeaderView contains wrapper view, which height is evaluated
with Auto Layout. Here I use evaluated height and update tableView's
tableViewHeaderView's frame.
New height for tableViewHeaderView is applied not without magic, that's why
I call -resetTableViewHeaderView.
And again, this doesn't work due to some internals of UITableView,
so -resetTableViewHeaderView call is scheduled in the main run loop.
*/
- (void)updateTableViewHeaderViewHeight
{
// get height of the wrapper and apply it to a header
CGRect Frame = self.tableView.tableHeaderView.frame;
Frame.size.height = self.tableHeaderViewWrapper.frame.size.height;
self.tableView.tableHeaderView.frame = Frame;
// this magic applies the above changes
// note, that if you won't schedule this call to the next run loop iteration
// you'll get and error
// so, I guess that's not a clean solution and could be wrapped in @try@catch block
[self performSelector:@selector(resetTableViewHeaderView) withObject:self afterDelay:0];
}
// yeah, guess there's something special in the setter
- (void)resetTableViewHeaderView
{
// whew, this could be animated!
[UIView beginAnimations:@"tableHeaderView" context:nil];
self.tableView.tableHeaderView = self.tableView.tableHeaderView;
[UIView commitAnimations];
}
All this works seamlessly after the initial autolayout pass. Later, if you change wrapper's contents so that it gains different height, it wont work for some reason (guess laying out UILabel requires several autolayout passes or something). I solved this with scheduling setNeedsLayout for the ViewController's view in the next run loop iteration.
I've created sample project for that: TableHeaderView+Autolayout.
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