计算内容界限(即动态单元格高度)
想要计算标签将占用的帧的常见用例是适当地调整表视图单元的大小。建议的方法是使用 NSString
方法 boundingRectWithSize:options:attributes:context:
。
options
采用字符串绘图选项:
NSStringDrawingUsesLineFragmentOrigin
应该用于多行标签- 如果有最大行数,则应使用
|
运算符添加NSStringDrawingTruncatesLastVisibleLine
attributes
属于影响属性字符串的属性(完整列表: Apple Docs ),但影响高度的因素包括:
-
NSFontAttributeName :非常重要,大小和字体系列是标签显示大小的关键部分。
-
NSParagraphStyleAttributeName :用于自定义文本的显示方式。这包括行间距,文本对齐,截断样式和一些其他选项。如果你没有明确更改任何这些值,则不必担心这一点,但如果你在 IB 上切换某些值可能很重要。
context
应 nil
因为主 NSStringDrawingContext
的使用情况是允许的字体大小以适合指定的矩形,如果我们计算一个动态的高度不应该是这样的。
目标 C.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *labelContent = cell.theLabel.text;
// you may choose to get the content directly from the data source if you have done minimal customizations to the font or are comfortable with hardcoding a few values
// NSString *labelContent = [self.dataSource objectAtIndexPath:indexPath];
// value may be hardcoded if retrieved from data source
NSFont *labelFont = [cell.theLabel font];
// The NSParagraphStyle, even if you did not code any changes these values may have been altered in IB
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = NSTextAlignmentCenter;
NSDictionary *attributes = @{NSFontAttributeName: labelFont,
NSParagraphStyleAttributeName: paragraphStyle};
// The width is also important to the height
CGFloat labelWidth = CGRectGetWidth(cell.theLabel.frame);
// If you have been hardcoding up to this point you will be able to get this value by subtracting the padding on left and right from tableView.bounds.size.width
// CGFloat labelWidth = CGRectGetWidth(tableView.frame) - 20.0f - 20.0f;
CGRect bodyBounds = [labelContent boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
return CGRectGetHeight(bodyBounds) + heightOfObjectsOnTopOfLabel + heightOfObjectBelowLabel;
}
Swfit 3
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var cell = tableView.cellForRow(atIndexPath: indexPath)!
var labelContent = cell.theLabel.text
var labelFont = cell.theLabel.font
var paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byWordWrapping
paragraphStyle.alignment = .center
var attributes = [NSFontAttributeName: labelFont, NSParagraphStyleAttributeName: paragraphStyle]
var labelWidth: CGFloat = cell.theLabel.frame.width
var bodyBounds = labelContent.boundingRect(withSize: CGSize(width: width, height: CGFLOAT_MAX), options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
return bodyBounds.height + heightOfObjectsOnTopOfLabel + heightOfObjectBelowLabel
}
相反,如果你确实设置了最大行数,则首先需要计算单行的高度,以确保我们不会获得高于允许大小的值:
// We calculate the height of a line by omitting the NSStringDrawingUsesLineFragmentOrigin option, which will assume an infinitely wide label
CGRect singleLineRect = [labelContent boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)
options:NSStringDrawingTruncatesLastVisibleLine
context:nil];
CGFloat lineHeight = CGRectGetHeight(singleLineRect);
CGFloat maxHeight = lineHeight * cell.theLabel.numberOfLines;
// Now you can call the method appropriately
CGRect bodyBounds = [labelContent boundingRectWithSize:CGSizeMake(width, maxHeight) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingTruncatesLastVisibleLine) attributes:attributes context:nil];
return CGRectGetHeight(bodyBounds) + heightOfObjectsOnTopOfLabel + heightOfObjectBelowLabel;