Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adjusting Container View's Height to Match Embedded UITableView

Using Storyboards and Autolayout, I have a UIViewController with a UIScrollView as the main view. I have several container views embedded in the scroll view. Some of those embedded container views contain UITableViews, each having cells of different heights. I'll need the tableView's height to be large enough to show all cells at once, as scrolling will be disabled on the tableView.

In the main UIViewController, container view's height has to be defined in order for the scroll view to work properly. This is problematic because there's no way for me to know how large my tableView will be once all it's cells of varying heights are finished rendering. How can I adjust my container view's height at runtime to fit my non-scrolling UITableView?

So far, I've done the following:

// in embedded UITableViewController
// 
- (void)viewDidLoad {
  // force layout early so I can determine my table's height
  [self.tableView layoutIfNeeded];

  if (self.detailsDelegate) {
        [self.detailsTableDelegate didDetermineHeightForDetailsTableView:self.tableView];
  }
}

// in my main UIViewController
// I have an IBOutlet to a height constraint set up on my container view
// this initial height constraint is just temporary, and will be overridden
// once this delegate method is called
- (void)didDetermineHeightForDetailsTableView:(UITableView *)tableView
{
  self.detailsContainerHeightConstraint.constant = tableView.contentSize.height;
}

This is working fine and I was pleased with the results. However, I have one or two more container views to add, which will have non-scrolling tableViews, and I'd hate to have to create a new delegate protocol for each container view. I don't think I can make the protocol I have generic.

Any ideas?

like image 795
djibouti33 Avatar asked May 12 '15 22:05

djibouti33


1 Answers

Here's what I ended up doing:

// In my embedded UITableViewController:
- (void)viewDidLoad
{
    [super viewDidLoad];

    self.tableView.rowHeight = UITableViewAutomaticDimension;
    self.tableView.estimatedRowHeight = 60.0;

    // via storyboards, this viewController has been embeded in a containerView, which is
    // in a scrollView, which demands a height constraint. some rows from our static tableView
    // might not display (for lack of data), so we need to send our table's height. we'll force
    // layout early so we can get our size, and then pass it up to our delegate so it can set
    // the containerView's heightConstraint.
    [self.tableView layoutIfNeeded];

    self.sizeForEmbeddingInContainerView = self.tableView.contentSize;
}

// in another embedded view controller:    
- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    self.sizeForEmbeddingInContainerView = self.tableView.contentSize;
}

// then, in the parent view controller, I do this:
// 1) ensure each container view in the storyboard has an outlet to a height constraint
// 2) add this:
- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    self.placeDetailsContainerHeightConstraint.constant = self.placeDetailsTableViewController.sizeForEmbeddingInContainerView.height;
    self.secondaryExperiencesContainerHeightConstraint.constant = self.secondaryExperiencesViewController.sizeForEmbeddingInContainerView.height;
}

I haven't done this yet, but it'd probably be best to create a Protocol with a property of CGSize sizeForEmbeddingInContainerView that each child view controller can adopt.

like image 172
djibouti33 Avatar answered Oct 13 '22 03:10

djibouti33