代码创建的UITableView单元格中图片显示宽度不一致问题排查
问题分析与解决方案
你遇到的这个图片偶尔尺寸异常的问题,核心原因是系统默认UITableViewCell的imageView自带自动布局约束,而你直接设置frame的操作会被系统的自动布局逻辑覆盖,尤其是在cell复用的时候——这也是为什么Storyboard创建的TableView没问题,因为你在Storyboard里设置的是约束,优先级比直接改frame高。
具体原因拆解
系统默认的UITableViewCell内部的imageView是通过自动布局来管理位置和尺寸的,当你在cellForRowAtIndexPath里直接修改它的frame,虽然当下可能生效,但等到系统触发布局更新(比如cell复用、滚动时的布局调整),自动布局约束会重新生效,把imageView的尺寸拉回默认值或者其他不符合预期的大小,就出现了偶尔过宽/过窄的情况。你加的[cell.imageView layoutIfNeeded];没效果,就是因为系统后续的布局更新会覆盖你的设置。
可行的解决方案
方案1:自定义UITableViewCell(最稳妥)
放弃系统默认的imageView,自己在自定义cell里添加UIImageView,完全掌控它的布局:
// 自定义MyTableViewCell.h @interface MyTableViewCell : UITableViewCell @property (nonatomic, strong) UIImageView *customImageView; @end // 自定义MyTableViewCell.m @implementation MyTableViewCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { _customImageView = [[UIImageView alloc] init]; _customImageView.contentMode = UIViewContentModeScaleAspectFill; _customImageView.clipsToBounds = YES; _customImageView.translatesAutoresizingMaskIntoConstraints = NO; [self.contentView addSubview:_customImageView]; // 设置固定尺寸和位置约束 [_customImageView.widthAnchor constraintEqualToConstant:24].active = YES; [_customImageView.heightAnchor constraintEqualToConstant:24].active = YES; [_customImageView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:0].active = YES; [_customImageView.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor].active = YES; // 设置圆角 _customImageView.layer.cornerRadius = 12; } return self; } @end
然后在cellForRowAtIndexPath里使用这个自定义cell,直接给customImageView赋值图片即可,再也不会有布局冲突的问题。
方案2:修改系统默认imageView的约束(不自定义cell的情况下)
如果不想自定义cell,那就直接修改系统imageView的自动布局约束,而不是设置frame:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellID = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; // 在这里一次性设置约束,避免重复添加 cell.imageView.translatesAutoresizingMaskIntoConstraints = NO; [cell.imageView.widthAnchor constraintEqualToConstant:24].active = YES; [cell.imageView.heightAnchor constraintEqualToConstant:24].active = YES; [cell.imageView.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:0].active = YES; [cell.imageView.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor].active = YES; cell.imageView.contentMode = UIViewContentModeScaleAspectFill; cell.imageView.clipsToBounds = YES; cell.imageView.layer.cornerRadius = 12; } // 赋值图片 cell.imageView.image = [UIImage imageNamed:[yourImageArray objectAtIndex:indexPath.row]]; return cell; }
注意要在cell初始化的时候添加约束,不要每次dequeue都加,否则会重复添加约束导致布局异常。
额外注意点
- 你的TableView设置了
rowHeight=24,和imageView的高度一致,要确保cell的contentView没有默认内边距,否则imageView可能会被裁剪。可以检查一下cell.contentView.layoutMargins是否为0。 - 如果用方案2,建议在cell的
prepareForReuse方法里重置imageView的图片,避免复用的时候显示错误的图片:
// 可以通过分类或者自定义cell实现 @implementation UITableViewCell (Reuse) - (void)prepareForReuse { [super prepareForReuse]; self.imageView.image = nil; } @end
内容的提问来源于stack exchange,提问作者user6631314
相关产品推荐
相关产品推荐

