UITableViewCell具有不同尺寸的图像

时间:2012-01-31 20:46:15

标签: objective-c ios cocoa-touch uitableview

我正在尝试将 ReusableCell 用于具有不同维度图像的单元格。图像放在220x150的黑盒子里,缩放UIViewContentModeScaleAspectFit

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"NewsTableViewCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    NewsItem *item = [self.fetchedResultsController objectAtIndexPath:indexPath];

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:item.imageUrl]];
    [cell.imageView setImage:[[UIImage alloc] initWithData:data]];
    [cell.imageView setBackgroundColor:[UIColor blackColor]];
    [cell.imageView setContentMode:UIViewContentModeScaleAspectFit];

    CGRect imageViewFrame = cell.imageView.frame;
    imageViewFrame.size.width = 220;
    imageViewFrame.size.height = 150
    [cell.imageView setFrame:imageViewFrame];

    [cell.textLabel setText:item.title];

    return cell;
}

上面的代码会产生如下布局,当在表格视图中滚动时,图像有时会发生变化。

UITableView with images

而不是这种非结构化布局,我希望图像像这样对齐:

Images in a black box

我在使用 ReusableCell 做错了什么?

EDIT1:

我正在尝试创建一个imageView并将此imageView作为超级视图添加到cell.contentView。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"NewsTableViewCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    NewsItem *item = [self.fetchedResultsController objectAtIndexPath:indexPath];

    UIImage *placeholderImage = [UIImage imageNamed:@"ImagePlaceholderThumb"]; //220x150

    UIImageView *imageView = [[UIImageView alloc] initWithImage:placeholderImage];

    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:item.imageUrl]];
    [imageView setImage:[[UIImage alloc] initWithData:data]];
    [imageView setBackgroundColor:[UIColor blackColor]];
    [imageView setContentMode:UIViewContentModeScaleAspectFit];

    CGRect imageViewFrame = imageView.frame;
    imageViewFrame.size.width = placeholderImage.size.width;
    imageViewFrame.size.height = placeholderImage.size.height;
    [imageView setFrame:imageViewFrame];

    [cell.contentView addSubview:imageView];

    [cell.textLabel setText:item.title];

    return cell;
}

以上代码产生以下结果:

UIImageView in superview

就像有些图像在两个单元格中可见。它们似乎没有保持我在 imageViewFrame 中设置的大小。你知道为什么吗?

2 个答案:

答案 0 :(得分:18)

快速修复将使用内容模式UIViewContentModeScaleAspectFill。图像将在一个或两个维度中拉伸,以填充整个图像视图边界。

您确实需要对UITableViewCell进行子类化才能正确执行此操作。

Thre是一个 lazy 解决方案,添加了一个新的UIImageView并使用了一个spacer,凯勒在他的回答中告诉你(随意接受他的回答,这只是丢失的代码)

tableView:cellForRowAtIndexPath:的摘录:

...
cell.textLabel.text = [NSString stringWithFormat:@"Cell #%i", indexPath.row];
cell.imageView.image = [UIImage imageNamed:@"spacer.png"]; /* spacer is 64 x 44 */
/* image view width should be ~ 64 px, otherwise it will overlap the text */
UIImageView *iv = [[UIImageView alloc] initWithFrame:(CGRect){.size={64, tableView.rowHeight}}];
switch (indexPath.row) {
    case 0:
        iv.image = [UIImage imageNamed:@"waterfall.png"];
        break;
    /* etc... */
}
if (indexPath.row < 3) {
    /* add black bg to cell w/ images */
    iv.backgroundColor = [UIColor blackColor];
}
iv.contentMode =  UIViewContentModeScaleAspectFit;
[cell.contentView addSubview:iv];
...

表格如下所示: aspect fit

您需要在现有单元格图像视图中设置占位符(上面为spacer.png)。它会将文本标签推向右侧。

您可以使用纵横填充并删除背景颜色位:

iv.contentMode =  UIViewContentModeScaleAspectFill;

该表看起来不对,因为图像是在边界外绘制的:

aspect fill without clipping

只需剪切到边界即可获得更好的结果:

iv.clipsToBounds = YES;

aspect fill

答案 1 :(得分:2)

为每个单元格创建一个UIImageView子视图,并将其创建到contentView。每个UIImageView都包含一个具有一致帧但带有选项UIViewContentModeScaleAspectFit的图像。然后只需将UIImageView的背景颜色设置为黑色。

我刚刚确认这是有效的,但你还需要创建一个占位符间隔图像,以确保textLabel移开。只需使它与图像的尺寸相同(使用字母装箱)。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString *CellIdentifier = @"Cell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    //spacer
    cell.imageView.image = [UIImage imageNamed:@"placeholder"];

    //imageview
    UIImageView *thumbnail = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 80, 44)];
    thumbnail.tag = kThumbTag;
    thumbnail.backgroundColor = [UIColor blackColor];
    thumbnail.contentMode = UIViewContentModeScaleAspectFit;
    [cell.contentView addSubview:thumbnail];
  }

  // Configure the cell...

  cell.textLabel.text = [NSString stringWithFormat:@"Cell %d", indexPath.row];

  cell.imageView.frame = CGRectMake(0, 0, 80, 44);

  UIImageView *thumb = (UIImageView*)[cell.contentView viewWithTag:kThumbTag];
  if (indexPath.row == 0) {
    [thumb setImage:[UIImage imageNamed:@"image1.png"]];
  } else {
    [thumb setImage:[UIImage imageNamed:@"image2.png"]];
  }

  return cell;
}

显然,这个例子不是延迟加载图像(我没有意识到你是从URL加载它们)。为此,我会使用带有EGOImageView或类似内容的子类。