UITableViewCell:如何在视网膜显示上给内置的 imageView 一个边距

Posted

技术标签:

【中文标题】UITableViewCell:如何在视网膜显示上给内置的 imageView 一个边距【英文标题】:UITableViewCell: how to give the built-in imageView a margin on retina display 【发布时间】:2011-02-05 19:03:53 【问题描述】:

我想在普通旧 UITableViewCell(分组样式)左侧的 UIImageView 上应用边距。

我发现的唯一方法(通过here)是在将 UIImage 附加到 UIImageView 之前调整它本身的大小。如果图像比单元格小,它将居中;留下所需的边距作为副作用。

嗯,这行得通,但现在我的图像很模糊,因为 100 unit 行高在 iPhone4 上不是 100 pixels,而是 200。所以我最终得到缩放到 90x90 pixels 的 UIImage,生成 90x90 unit(180x180 像素)的 UIImageView 图像。输入丑陋的模糊。

所以我的问题是:如何在不过度下采样图像的情况下实现 imageView 周围的边距? (理想情况下根本不需要下采样 - 我需要保留原件以备后用)。

我觉得我错过了一些明显的东西;我真的不想为此实现自定义单元类。

【问题讨论】:

【参考方案1】:

谢谢大家,我想出了一个不需要子类化的“解决方案”。

我所做的仍然是对图像进行下采样,但缩小到 2 倍大小(问题示例中的 180x180)。 然后,当我从我使用的处理过的 CGImage 创建最终的 UIImage 时:

<em>UIImage:</em> +(UIImage *)imageWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation

并将 scale: 设置为 2。现在一切正常。但我仍在创建重复图像只是为了让 UIKit 满意。

【讨论】:

【参考方案2】:

在你的 UITableViewCell 子类中实现这个方法

-(void) layoutSubviews

    [super layoutSubviews];
    self.imageView.frame = CGRectInset(self.imageView.frame, 5, 5);

【讨论】:

或者在 UITableViewCell 上创建一个具有此属性的类别,并具有一个额外的结构或 CGSize 属性,您可以将其设置为 5、5 或任何您需要的值。【参考方案3】:

注意:我还没有测试过这些,所以UITableViewCell 可能会覆盖其中的一些设置,以根据自己的内部逻辑布置其子视图。

您是否尝试过仅调整图像视图的框架?试试这个:

UITableViewCell * tableViewCell = [[[UITableViewCell alloc] init] autorelease];
tableViewCell.imageView.image = [UIImage imageNamed:@"table-view-image"];

CGRect imageViewFrame = tableViewCell.imageView.frame;
imageViewFrame.origin.x += 10.0f;
tableViewCell.imageView.frame = imageViewFrame;

这只会使图像视图比其正常的x 坐标多 10 个点。如果要两边都pad,也可以把image view上的contentMode属性设置为UIViewContentModeCenter,并调整它的宽度:

UITableViewCell * tableViewCell = [[[UITableViewCell alloc] init] autorelease];
tableViewCell.imageView.image = [UIImage imageNamed:@"table-view-image"];
tableViewCell.imageView.contentMode = UIViewContentModeCenter;

CGRect imageViewFrame = tableViewCell.imageView.frame;
imageViewFrame.size.width += 20.0f;
tableViewCell.imageView.frame = imageViewFrame;

这将使图像视图宽 20 点,但由于内容模式设置为居中,图像将在不拉伸的情况下绘制。如果您的图像尺寸正确,这将有效地将图像在左右两侧填充 10 个点。但是,您需要注意,如果您这样做,您提供的UIImage 必须已经是适合图像视图的确切尺寸。 contentMode 的默认设置是UIViewContentModeScaleToFill,所以它会自动缩放图像以填充图像视图的框架。将其设置为 UIViewContentModeCenter 将不再执行此操作,但会将实际图像居中。

【讨论】:

【参考方案4】:

在我的例子中,我使用了我自己的继承自 UITableViewCell 的子类。 它非常干净且易于使用。 此外,我可以使用不同大小的图像来调整此单元格的大小。 关键是使用将替换常规imageView的附加属性@

1:在子类中,我添加了一个属性mainImageView,可以用来代替imageView

@property (nonatomic, retain) UIImageView *mainImageView;

2:然后在- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier。 我分配并初始化了mainImageView。 您可以为mainImageView 设置任何框架(矩形)。 将其作为子视图添加到contentView。 我使用insetImageView 将其与 `contentView' 的垂直中间对齐。

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

    if (self) 
        // Initialization code.     
        mainImageView = [[UIImageView alloc] initWithFrame:frameCellMainImageView];
        [self.contentView addSubview:mainImageView];

                insetImageView = (sizeRowHeightTwoLinedDetail - frameCellMainImageView.size.height) / 2.0;

    

    return self;

3:覆盖- (void)layoutSubviews 以确保textLabeldetailTextLabel 等其他属性将其框架设置为与添加属性mainImageView 相得益彰

- (void)layoutSubviews 
    [super layoutSubviews];

    CGRect frameImageView = frameCellMainImageView;
    frameImageView.origin.x = insetImageView;
    frameImageView.origin.y = insetImageView;

    [self.mainImageView setFrame:frameImageView];

    // Use changed frame
    frameImageView = self.mainImageView.frame;
    CGFloat newLeftInset = frameImageView.size.width + insetImageView;

    CGRect frameTextLabel = self.textLabel.frame;
    CGRect frameDetailLabel = self.detailTextLabel.frame;

    frameTextLabel.origin.x += newLeftInset;
    frameDetailLabel.origin.x += newLeftInset;

    CGFloat newTextWidth = 320.0;
    newTextWidth -= newLeftInset;
    newTextWidth -= insetImageView;
    newTextWidth -= insetImageView;

    frameTextLabel.size.width = newTextWidth;
    frameDetailLabel.size.width = newTextWidth;

    [self.textLabel setFrame:frameTextLabel];
    [self.detailTextLabel setFrame:frameDetailLabel];

4:在UITableDataSourceDelegate方法中使用此单元格时,使用cell.mainImageView接收消息,而不是常规的cell.imageView

【讨论】:

以上是关于UITableViewCell:如何在视网膜显示上给内置的 imageView 一个边距的主要内容,如果未能解决你的问题,请参考以下文章

如何合并两个图像以进行视网膜显示(@2x)?

如何在视网膜显示器上强制放大模式?

如何在不损失视网膜显示质量的情况下将 UIView 捕获到 UIImage

使 UIButton 图像在视网膜显示器上显得清晰完美

iOS SDWebImage - 如何正确处理不同设备上的视网膜图像?

为啥视网膜设备上的图标不显示?