計算內容界限(即動態單元格高度)
想要計算標籤將佔用的幀的常見用例是適當地調整表檢視單元的大小。建議的方法是使用 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;