Custom TableViewCell with dynamic height and full width image using Autolayout

时间:2015-07-28 16:40:15

标签: ios objective-c autolayout tableview tableviewcell

I'm really stuck using autolayout and a custom tableviewcell.

I want my tableviewcell to have a dynamic height. The table cell should contain an image with the same width as the tableviewcell and the height should adjust based on an aspect ratio of 0.6

This is what it should look like

But this is what I get

To give you a clear look of what is going on I gave the tableViewCell and it's subviews some pretty background colors…

  • Green = thumbnailView
  • Blue = self
  • Red = contentView
  • Purple = hotspotNameLabel
  • Yellow = categoryLabel

This is what my code looks like:

Initializer:

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {

    self.contentView.backgroundColor = [UIColor redColor];
    self.backgroundColor = [UIColor blueColor];

    CGFloat imageAspectRatio = 720/432;
    CGFloat imageHeight = self.contentView.bounds.size.width / imageAspectRatio;

    CGRect imageFrame = CGRectMake(0, 0, self.contentView.bounds.size.width,imageHeight);

    self.thumbnailView = [[UIImageView alloc] initWithFrame:imageFrame];
    [self.thumbnailView setBackgroundColor:[UIColor greenColor]];
    [self.thumbnailView setContentMode:UIViewContentModeScaleAspectFill];
    [self.thumbnailView.layer setMasksToBounds:true];
    [self.contentView addSubview:self.thumbnailView];

    self.hotspotNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(40, 15, self.contentView.bounds.size.width - 80, 20)];
    [self.hotspotNameLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
    [self.hotspotNameLabel setTextColor:[UIColor colorWithWhite:(32/255.0) alpha:1]];
    [self.hotspotNameLabel setLineBreakMode:NSLineBreakByWordWrapping];
    [self.hotspotNameLabel setNumberOfLines:0]; // Unlimited Lines
    [self.hotspotNameLabel setBackgroundColor:[UIColor purpleColor]];
    [self.hotspotNameLabel setFont:[UIFont fontWithName:@"AvenirNext-Medium" size:20]];

    [self.contentView addSubview:self.hotspotNameLabel];

    // Category Label
    self.categoryLabel = [[CategoryLabel alloc] initWithFrame:CGRectMake(40, 15, self.contentView.bounds.size.width - 80, 10)
                                                   categoryId:22 categoryName:@"Food"];
    [self.contentView addSubview:self.categoryLabel];

    // Constraints

    [self.contentView setTranslatesAutoresizingMaskIntoConstraints:false];
    [self.hotspotNameLabel setTranslatesAutoresizingMaskIntoConstraints:false]; // Enables autosizing
    [self.categoryLabel setTranslatesAutoresizingMaskIntoConstraints:false];
    [self.thumbnailView setTranslatesAutoresizingMaskIntoConstraints:false];

    [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.thumbnailView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem: self.contentView attribute:NSLayoutAttributeWidth multiplier:1.0f constant:0]];
    [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.thumbnailView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem: self.contentView attribute:NSLayoutAttributeWidth multiplier:0.6f constant:0]];

    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[nameLabel]-0-|" options:0 metrics:nil views:@{@"nameLabel": self.hotspotNameLabel}]];
    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[thumbnail]-20-[nameLabel]-10-[categoryLabel]-0-|" options:0 metrics:nil views:@{@"thumbnail": self.thumbnailView,@"nameLabel": self.hotspotNameLabel, @"categoryLabel":self.categoryLabel}]];


}
return self;}

Layout subviews:

-(void)layoutSubviews {

[super layoutSubviews];

[self.contentView setNeedsLayout];
[self.contentView layoutIfNeeded];


self.hotspotNameLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.hotspotNameLabel.bounds);
}

tableView:HeightForRowAtIndexPath:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [self heightForLargeCellAtIndexPath:indexPath];
}

- (CGFloat)heightForLargeCellAtIndexPath:(NSIndexPath *)indexPath {

    LargeHotspotCell *sizingCell = [[LargeHotspotCell alloc] init];

    [self configureLargeCell:sizingCell atIndexPath:indexPath];

    [sizingCell setNeedsLayout];
    [sizingCell layoutIfNeeded];

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

    return height + 1 ;
}

1 个答案:

答案 0 :(得分:0)

在这里,您将解释自动布局的基本概念。 您的第一步应该是UITableviewCell的子类化,我将我的新单元DynamicTableViewCell命名为并在身份检查器中分配。

enter image description here

我将UILabel和UIImageView拖放到contentView中。 在具有UILabel约束的屏幕截图下面,我同时添加了前导和尾随空间约束,以使我的标签等于contentView宽度。它与细胞底部对齐。

enter image description here

现在,是时候为UIImageView分配约束了。我正在添加宽高比0.6(imageHeight / imageWidth = 0.6)并向contentView添加前导和尾随空格。随意玩常数以达到您想要的目的。

enter image description here

iphone5,iphone6模拟器的最终结果

您的图像高度(绿色)在5s屏幕中为60pt,在6屏幕中为70pt并且宽度正确调整大小:

enter image description here

为了更好地理解,我发布了Working Sample Project on github