3

I would like to dynamically adjust the width of a UIImage inside of a UITableViewCell, I'm using the storyboard to design the UITableViewCell, I just added a label and an image, the properties get updated correctly, I'm even loading the value of the width into the label to show that it's the correct value, for the image, I'm loading a background image that I want to repeat, but the image won't update the width initially, if I scroll up and down, the images are shown as expected, here's the code for the cellForRowAtIndexPath, I've also tried to put the code on the willDisplayCell method, same result

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"mycustomcell"];
    int r = [[data objectAtIndex:indexPath.row] intValue];
    UIImageView *img = (UIImageView *)[cell viewWithTag:2];
    img.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"some_img" ofType:@"png"]]];
    CGRect frame = img.frame;
    frame.size.width = r*16;
    img.frame = frame;

    int n = img.frame.size.width;
    UILabel *label = (UILabel *)[cell viewWithTag:1];
    label.text = [NSString stringWithFormat:@"custom %d", n];
    [cell setNeedsDisplay];
    return cell;
}

I just want this to work initially as it works after scrolling, thoughts?

ElGavilan
  • 6,610
  • 16
  • 27
  • 36
BlackTigerX
  • 6,006
  • 7
  • 38
  • 48
  • Do you have Auto Layout enabled in the storyboard? – Arek Holko Oct 13 '13 at 19:19
  • you never create a cell – vikingosegundo Oct 13 '13 at 19:22
  • @vikingosegundo If using cell prototypes, you don't have to create it. The `dequeueReusableCellWithIdentifier` will create it for you. – Rob Oct 13 '13 at 20:50
  • 1
    @Rob, no, `dequeueReusableCellWithIdentifier:forIndexPath:` would create it. – vikingosegundo Oct 13 '13 at 20:50
  • @vikingosegundo No. You are correct that for iOS 6+, you should use the rendition with the `forIndexPath` (for performance reasons), but both instantiate the cell if you have a prototype. If it didn't, his code would have generated an exception. The behavior he describes is unrelated to the choice to use the `forIndexPath` rendition or not. – Rob Oct 13 '13 at 21:14
  • Yes, Auto Layout is enabled – BlackTigerX Oct 14 '13 at 04:02
  • 2
    @BlackTigerX Then, give the cell's imageview a width constraint and change the `constant` for that constraint, rather than adjusting the `frame` for the imageview. In general, in autolayout you should be altering constraints, not changing `frame` values. – Rob Oct 14 '13 at 16:47

2 Answers2

7

The dynamic resizing of contents of a tableview cell is a well known problem. While there are kludgy workarounds, I believe proper solution depends upon whether you're using autolayout or not:

  • If using auto layout, make sure that your cell's image view has a width constraint, and then you can change the constraint's constant:

    for (NSLayoutConstraint *constraint in img.constraints)
    {
        if (constraint.firstAttribute == NSLayoutAttributeWidth)
            constraint.constant = r*16;
    }
    

    Frankly, I'd rather use a custom UITableViewCell subclass and have an IBOutlet for the width constraint (e.g. imageWidthConstraint), and it saves you from having to enumerate through the constraints to find the right one, and you can simply:

    cell.imageWidthConstraint.constant = r*16;
    
  • If not using auto layout, you should subclass UITableViewCell, use that for your cell prototype's base class, and then override layoutSubviews, and resize the image view there. See Changing bounds of imageView of UITableViewCell.

Regardless of which approach you adopt, using a UITableViewCell subclass eliminates the need to use viewForTag construct, which makes the view controller code a little more intuitive.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 2
    This should really be the accepted answer, not from the original poster to just remove auto layout. – Michael Nov 05 '13 at 16:23
  • This really should be the correct answer. Removing autolayout is not an option, it can cause much worse problems. – Daniel Lima Oct 07 '14 at 07:54
  • I m getting issues using this solution as well. On initial load, the width change doesn't reflect. After scrolling the table the width changes as per the code. – user2955351 Jun 14 '16 at 07:32
1

argh, removing Auto Layout fixed the problem

BlackTigerX
  • 6,006
  • 7
  • 38
  • 48