Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic TableViewCell height to fit downloaded image

I was following this answer: Using Auto Layout in UITableView for dynamic cell layouts & variable row heights but it lacks 2 things that made me unable to complete it:

  1. I set the constraints in the Storyboard prototype cell, not programmatically
  2. The image download is done async.

Basically I'm downloading an image using SDWebImage, and resizing the UIImageView's height so that it displays the entire image (scaled down, of course). The problems I'm having are commented in the code below:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

   // dequeue cell using identifier

  [cell.pictureView sd_setImageWithUrl:myUrl completed:^( ... block ...) {

       // This code will scale down the UIImage to the UIImageView's width maitaining
       // its aspect ratio, and also will resize the UIImageView's to match the scaled-down UIImage's height

       if(image != nil) {
         CGSize imageSize = [image size];
         CGSize imageViewSize = CGSizeMake(280.0, 100.0);

         CGFloat correctHeight = (imageViewSize.width / imageSize.width) * imageSize.height;

         [[cell pictureView] setFrame:CGRectMake([[cell pictureView] frame].origin.x,
                                                  [[cell pictureView] frame].origin.y,
                                                  CGRectGetWidth([[cell pictureView] bounds]),
                                                  correctHeight)];

           // At this point, the subviews are all set. Since this happens async, what method do I call to re-calculate this row's height.

  }];


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    static int defaultHeight = 230;

    // Get's the offscreen cell used only for calculation purposes
    WKZEventsCell *cell = [[self offscreenCells] objectForKey:CellIdentifier];
    if(!cell) {

        // HOW DO I GET A REFERENCE TO A PROTOTYPED CELL INSIDE THE STORYBOARD??? 
        // note that calling dequeueReusableCellWithIdentifier:CellIdentifier will cause a memory leak      

        cell = ??????
        [[self offscreenCells] setObject:cell forKey:CellIdentifier];
    }

    WKZEvent *event = [[self eventList] objectAtIndex:[indexPath row]];
    [[cell titleLabel] setText:[event title]];
    [[cell placeLabel] setText:[event title]];
    [[cell pictureView] setImage:image];


    // Even tho this should be in memory cache right now, I'm pretty sure this call is still asynchronous, so this might make the whole thing wont work.
    [cell.pictureView sd_setImageWithUrl:myUrl


    // THIS METHODS ARE COMMENTED BECAUSE MY CONSTRAINTS ARE SET IN STORYBOARD, BUT NOT SURE IF I'M RIGHT AT THIS ONE
    //[cell setNeedsUpdateConstraints];
    //[cell updateConstraintsIfNeeded];

    // I DONT HAVE A MULTILINE LABEL SO I DONT CALL THIS. NOT SURE ABOUT THIS ONE EITHER
    //cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));

    [cell setNeedsLayout];
    [cell layoutIfNeeded];

    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    height += 1;

    NSLog(@"%f", height);

    return height;
}
like image 475
Christopher Francisco Avatar asked Aug 09 '14 01:08

Christopher Francisco


1 Answers

Storyboard:

  • Add a new cell to your table view
  • Add a new image view to the cell
  • Optionally set a placeholder image for the image view
  • Make cell's constraints describe its height unambiguously

Be sure to leave Row Height of the cell set to Default

Code:

Make the table view to self-size cells:

var tableview: UITableView {
    didSet {
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 44
    }
}

At runtime, start loading the image asynchronously as soon as possible.

When downloaded, load the image to the image view and execute:

tableView.beginUpdates()
tableView.endUpdates()
like image 83
Rudolf Adamkovič Avatar answered Sep 22 '22 11:09

Rudolf Adamkovič