sizeWithFont: 和 sizeWithAttributes: 不适用于长单行
sizeWithFont: and sizeWithAttributes: don't work for a long single line
我正在尝试为 table 中的单元格设置动态高度,高度应基于文本长度和最大宽度。
当此文本出现在单行中且没有行分隔符时,就会出现问题。不管文本有多大,如果没有行分隔符,它会检测到文本适合一行,所以我的单元格高度不会增加。
我是不是做错了什么?我怎样才能实现它?谢谢
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat cellheight = 35.0f; // BASE
NSString *text = @"...";
if (text) {
UIFont *font = (indexPath.row == 0) ? [UIFont systemFontOfSize:14] : [UIFont systemFontOfSize:12];
CGSize constraintSize = CGSizeMake(self.tableView.frame.size.width, CGFLOAT_MAX);
if (IS_EARLIER_THAN_IOS7) {
CGSize size = [text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:NSLineBreakByCharWrapping];
cellheight += size.height;
} else {
CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:12.0f]}];
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
cellheight += adjustedSize.height;
}
return (indexPath.row == 0) ? cellheight + 40.0f : cellheight;
}
}
有一种更简单的方法可以做到这一点:
首先将文字设置为UILabel
,并设置所有需要的字体、字号。等。然后在标签上调用sizeThatFits
方法。
CGSize sizze =[itemLabel sizeThatFits:CGSizeMake(itemNameLabelWidth, CGFLOAT_MAX)];
另外不要忘记在调用 sizeThatFits:
之前设置 numberOfLines
和 lineBreakMode
itemLabel.numberOfLines=0;
itemLabel.lineBreakMode=NSLineBreakByWordWrapping;
注意 1 : 调用 sizeThatFits
不会将新框架设置到 UILabel,它只是计算并 returns 新框架。然后,您必须通过添加 x 和 y 原点值将框架设置为标签。这样就变成了:
CGSize sizze =[itemLabel sizeThatFits:CGSizeMake(itemNameLabelWidth, CGFLOAT_MAX)];
CGRect namelabelFrame = itemLabel.frame;
namelabelFrame.size = sizze;
itemLabel.frame = namelabelFrame;
注2:这段代码在cellForRowAtIndexPath:
里没问题,但是在heightForRowAtIndexPath:
里面计算高度的时候可能要稍微优化一下这段代码.由于您没有要使用的单元格,您可以初始化一个 UILabel
对象并对其执行此代码以估计高度。但是在 heightForRowAtIndexPath:
中进行 UIView
初始化并不是一个好主意,因为它们会在滚动时显着影响性能。
因此,您要做的是将已初始化(并应用所有格式)UILabel
作为 class 变量,并将其重新用于高度计算。
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode NS_DEPRECATED_IOS(2_0, 7_0, "Use -boundingRectWithSize:options:attributes:context:") __TVOS_PROHIBITED; // NSTextAlignment is not needed to determine size
您应该使用 "boundingRectWithSize:options:attributes:context:" 而不是 "sizeWithAttributes:"。
这是一个示例
CGSize size = [text boundingRectWithSize:CGSizeMake(_myTableView.frame.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} context:nil].size;
我正在尝试为 table 中的单元格设置动态高度,高度应基于文本长度和最大宽度。
当此文本出现在单行中且没有行分隔符时,就会出现问题。不管文本有多大,如果没有行分隔符,它会检测到文本适合一行,所以我的单元格高度不会增加。
我是不是做错了什么?我怎样才能实现它?谢谢
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat cellheight = 35.0f; // BASE
NSString *text = @"...";
if (text) {
UIFont *font = (indexPath.row == 0) ? [UIFont systemFontOfSize:14] : [UIFont systemFontOfSize:12];
CGSize constraintSize = CGSizeMake(self.tableView.frame.size.width, CGFLOAT_MAX);
if (IS_EARLIER_THAN_IOS7) {
CGSize size = [text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:NSLineBreakByCharWrapping];
cellheight += size.height;
} else {
CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:12.0f]}];
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
cellheight += adjustedSize.height;
}
return (indexPath.row == 0) ? cellheight + 40.0f : cellheight;
}
}
有一种更简单的方法可以做到这一点:
首先将文字设置为UILabel
,并设置所有需要的字体、字号。等。然后在标签上调用sizeThatFits
方法。
CGSize sizze =[itemLabel sizeThatFits:CGSizeMake(itemNameLabelWidth, CGFLOAT_MAX)];
另外不要忘记在调用 sizeThatFits:
numberOfLines
和 lineBreakMode
itemLabel.numberOfLines=0;
itemLabel.lineBreakMode=NSLineBreakByWordWrapping;
注意 1 : 调用 sizeThatFits
不会将新框架设置到 UILabel,它只是计算并 returns 新框架。然后,您必须通过添加 x 和 y 原点值将框架设置为标签。这样就变成了:
CGSize sizze =[itemLabel sizeThatFits:CGSizeMake(itemNameLabelWidth, CGFLOAT_MAX)];
CGRect namelabelFrame = itemLabel.frame;
namelabelFrame.size = sizze;
itemLabel.frame = namelabelFrame;
注2:这段代码在cellForRowAtIndexPath:
里没问题,但是在heightForRowAtIndexPath:
里面计算高度的时候可能要稍微优化一下这段代码.由于您没有要使用的单元格,您可以初始化一个 UILabel
对象并对其执行此代码以估计高度。但是在 heightForRowAtIndexPath:
中进行 UIView
初始化并不是一个好主意,因为它们会在滚动时显着影响性能。
因此,您要做的是将已初始化(并应用所有格式)UILabel
作为 class 变量,并将其重新用于高度计算。
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode NS_DEPRECATED_IOS(2_0, 7_0, "Use -boundingRectWithSize:options:attributes:context:") __TVOS_PROHIBITED; // NSTextAlignment is not needed to determine size
您应该使用 "boundingRectWithSize:options:attributes:context:" 而不是 "sizeWithAttributes:"。
这是一个示例
CGSize size = [text boundingRectWithSize:CGSizeMake(_myTableView.frame.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} context:nil].size;