通常,我支持可变高度单元的方法是定义一个类方法,该方法可以计算给定模型对象的大小:
+ (CGFloat)heightForBracket:(Bracket*)bracket;
使其成为类方法的美妙之处在于,您可以与实际实现布局的代码共享常量(填充值、字体大小、缩进级别等),而无需将它们暴露给任何其他类。如果您想在将来更改这些常量,您只需在单元子类中的一处进行更改。一个示例子类实现:
#define kPaddingHorizontal 10.0
#define kPaddingVertical 10.0
#define kFontSizeName 17.0
+ (CGFloat)heightForBracket:(Bracket*)bracket {
// determine the dimensions of the name
UIFont *nameFont = [UIFont systemFontOfSize:kFontSizeName];
CGFloat nameSize = [bracket.name sizeWithFont:nameFont
constrainedToSize:CGSizeMake(300, CGFLOAT_MAX) // 300 is the width of your eventual label
lineBreakMode:NSLineBreakByWordWrapping];
// Apple recommends all cells be at least 44px tall, so we enforce a minimum here
return MAX(44, nameSize.height + 20 + kPaddingVertical*2); // 20 is space for the subtitle label
}
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
if (self) {
// bracket name
self.textLabel.numberOfLines = 0; // 0 makes this variable height
self.textLabel.font = [UIFont systemFontOfSize:kFontSizeName];
self.textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
self.textLabel.backgroundColor = [UIColor clearColor];
// if you wanted to hardcode a specific width, to a subview do it here as a constant and then share it with heightForBracket:
// bracket number
self.detailTextLabel.numberOfLines = 1;
self.detailTextLabel.font = [UIFont systemFontOfSize:14.0];
self.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
self.detailTextLabel.backgroundColor = [UIColor clearColor];
}
return self;
}
- (void)setBracket:(Bracket*)bracket {
_bracket = bracket;
self.textLabel.text = bracket.name;
self.detailTextLabel.text = [NSString stringWithFormat:@"%@", bracket.bracketId];
}
然后您可以heightForBracket:
致电tableView:heightForRowAtIndexPath:
:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
Bracket *bracket = [brackets objectAtIndex:indexPath.row];
return [BracketTableCell heightForBracket:bracket];
}
tableView:cellForRowAtIndexPath:
变得非常简单,只需在单元格上设置适当的括号:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"BCell";
BracketTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[BracketTableCell alloc] initWithReuseIdentifier:CellIdentifier];
}
Bracket *bracket = [brackets objectAtIndex:indexPath.row];
cell.bracket = bracket;
return cell;
}
几点注意事项:
- 这假设单元格没有使用自动布局
- 这明确硬编码单元格/标签的宽度,可能适合也可能不适合您的用例
- 你永远不应该命名一个属性
description
,因为这是协议中已经存在的方法NSObject
- 其他增强功能将缓存结果
heightForBracket:
以提高滚动性能,特别是如果您开始为大量子视图执行大小调整逻辑