在 UITableViewCell 中自动调整 UILabel 的大小
Posted
技术标签:
【中文标题】在 UITableViewCell 中自动调整 UILabel 的大小【英文标题】:Autoresizing of UILabels in a UITableViewCell 【发布时间】:2011-02-23 15:00:53 【问题描述】:我将自己的UILabel
s 添加到UITableViewCell
的contentView
中,因为我需要对布局进行比默认 UITableViewCellStyles 提供的更多控制。本质上,我希望 detailLabel 优先于 textLabel,因此 textLabel 会被截断。
我的UITableViewController
中有以下代码:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString * const kCellIdentifier = @"CustomCell";
UITableViewCell * cell =
[tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
UILabel * titleLabel, * dateLabel;
if(cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:kCellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
titleLabel = [[[UILabel alloc] init] autorelease];
titleLabel.tag = kTitleLabelTag;
titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
dateLabel = [[[UILabel alloc] init] autorelease];
dateLabel.tag = kDateLabelTag;
dateLabel.textColor = [UIColor blueColor];
dateLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[cell.contentView addSubview:titleLabel];
[cell.contentView addSubview:dateLabel];
[self configureCell:cell atIndexPath:indexPath];
return cell;
- (void)configureCell:(UITableViewCell *)pCell
atIndexPath:(NSIndexPath *)pIndexPath
const float kHeight = 44.0, kLeftIndent = 8.0, kOverallWidth = 293.0,
kGap = 1.0;
UILabel * titleLabel, * dateLabel;
titleLabel = (UILabel *)[pCell.contentView viewWithTag:kTitleLabelTag];
dateLabel = (UILabel *)[pCell.contentView viewWithTag:kDateLabelTag];
NSString * dateText = @"9:39 AM";
// Calculate the size of dateLabel
CGSize dateSize = [dateText sizeWithFont:[dateLabel font]
constrainedToSize:CGSizeMake(kOverallWidth, kHeight)];
const float dateXPos = kOverallWidth - dateSize.width;
dateLabel.frame = CGRectMake(dateXPos, 0.0, dateSize.width, kHeight);
titleLabel.frame = CGRectMake(kLeftIndent, 0.0,
dateXPos - kLeftIndent - kGap, kHeight);
titleLabel.text = @"Some potentially very long text which will be wrapped.";
dateLabel.text = dateText;
pCell.contentView.backgroundColor = [UIColor purpleColor];
上面的代码产生了错误的结果。最初显示表格视图时,它看起来像 this image of the renderings 中的图 1)。
所以在所有dateLabel
s 的右侧有一个不需要的空白。 (紫色背景只是为了更好地了解正在发生的事情)
当像在图像中的 2) 那样向上拖动 tableview 时,它会弹回并看起来像 3)。
第一行现在正好是我想要的布局,它在configureCell:atIndexPath:
中计算。我猜这种行为的发生是因为单元被重新使用然后再次配置。
所以感觉好像我缺少某种初始化,我尝试调用pCell
和pCell.contentView
的setNeedsLayout
和layoutSubviews
,但从未实现初始正确渲染。
只有当我将titleLabel
和dateLabel
的autoresizingMask
设置为UIViewAutoresizingNone
时,我才能得到正确的初始渲染,但是滑动删除不起作用,因为删除按钮在dateLabel
上渲染.
我必须在我的代码中进行哪些更改,以使所有单元格最初呈现就像第三张图片中的第一个单元格一样?
谢谢!
PS:我想内联图片,但不幸的是我没有足够的声誉。
【问题讨论】:
+1 用于使用const float
而不是 #define
以获得更好的类型安全性。我知道在 Apple 的示例代码中他们经常使用预编译器指令,但使用 consts 更好。恕我直言
【参考方案1】:
一个好的,也许更简单的方法是:
首先创建一个自定义 UITableViewCell 子类,您可以使用 Interface Builder 进行设置。如果“MyTableViewCell”是您的自定义单元格视图,您可以像这样在 CellForRowAtIndexPath 中初始化它:
MyTableViewCellClass *cell = (MyTableViewCellClass *)[tableView dequeueReusableCellWithIdentifier:@"MyTableViewCellClass"] autorelease];
if (!cell)
cell = [[[MyTableViewCellClass alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyTableViewCellClass"] autorelease];
// Call specific methods on your cell to pass information to it, not for display
[cell setProperties:...];
然后在你的自定义 UITableViewCell 子类中实现 layoutSubviews 方法。例如:
-(void) layoutSubviews
// You must call this first to make sure your cell gets current parent information
[super layoutSubviews];
// Retrieve the content view bounds. This will include the edit symbols when present (delete button and ordering symbol
float inset = 5.0;
CGRect bounds = [[self contentView] bounds];
// Keep on going here with your own view layout.
这样做您基本上将单元模型 (CellForRowAtIndexPath) 与单元视图(您的单元绘图的自定义实现)分开。如果您稍后更改单元格的实现(布局),您只需更改单元格布局即可轻松完成此操作,而无需担心 CellForRowAtIndexPath 方法。
【讨论】:
谢谢!在子类的layoutSubviews
方法中从configureCell:
执行代码,然后使用bounds.size.width
而不是我固定的kOverallWidth
解决了它。
@Torsten 很高兴它有帮助。祝你的应用好运。【参考方案2】:
如果您使用 storyboard ,您应该在文件检查器中禁用“使用自动布局”!
然后设置单元格的属性autoresizesSubviews
- (void)awakeFromNib
// Initialization code
self.autoresizesSubviews=YES;
最后一步是配置 Label 的框架,覆盖 UITableViewCell 类的 layoutSubviews 方法
-(void)layoutSubviews
[super layoutSubviews];
CGFloat top=VerticalPadding;
CGFloat left=HorizentalPadding;
CGFloat width=CGRectGetWidth(self.frame)-2*HorizentalPadding;
CGFloat height=CGRectGetHeight(self.frame)-2*VerticalPadding;
CGRect rect=CGRectMake(left, top, width, height);
self.Label.frame=rect;
【讨论】:
以上是关于在 UITableViewCell 中自动调整 UILabel 的大小的主要内容,如果未能解决你的问题,请参考以下文章
在 UITableViewCell 中自动调整 UILabel 的大小
在具有自动布局的 UITableViewCell 中动态调整大小的 UIWebView - 违反约束