嵌入NSTextAttachment时,高UILabel中缺少行

我可以使用转义的换行符( @"\n" )创建多行NSAttributedString 。 使用iOS 7,我现在可以在属性字符串中嵌入UIImage (通过NSTextAttachment )。

我注意到每当我将UILabelattributedText设置为带有嵌入图像的多行属性字符串时,实际显示的行数标签的高度成反比 。 例如,当标签的高度为80时,会出现两条线; 当高度大约为100时,只出现第二条线; 当高度约为130时,什么都没有出现。

尝试在UITableViewCell内并排放置多个UILabel并使标签与单元格高度增长(垂直)时发生此问题。

任何人都可以解释为什么会这样吗? 有没有人知道不涉及使UILabel变小的解决方法?


示例代码:

 @implementation SOViewController - (void)viewDidLoad { [super viewDidLoad]; NSMutableAttributedString *text1 = [[NSMutableAttributedString alloc] init]; [text1 appendAttributedString:[[NSAttributedString alloc] initWithString:@"Line 1\n"]]; [text1 appendAttributedString:[[NSAttributedString alloc] initWithString:@"Line 2"]]; UIImage *image = [UIImage imageNamed:@"17x10"]; //some PNG image (17px by 10px) NSTextAttachment *attachment = [[NSTextAttachment alloc] init]; attachment.image = image; attachment.bounds = CGRectMake(0, 0, image.size.width, image.size.height); NSMutableAttributedString *text2 = [[NSMutableAttributedString alloc] init]; [text2 appendAttributedString:[[NSAttributedString alloc] initWithString:@"Line 1\n"]]; [text2 appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]]; [text2 appendAttributedString:[[NSAttributedString alloc] initWithString:@"Line 2"]]; CGFloat margin = 20; //shows both lines when height == 80 //shows line 2 when 90 <= height <= 120 //shows nothing when height == 130 CGFloat height = ???; CGFloat width = 200; UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(margin, margin, width, height)]; UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectMake(margin, margin + height, width, height)]; [self.view addSubview:label1]; [self.view addSubview:label2]; label1.backgroundColor = [UIColor orangeColor]; label2.backgroundColor = [UIColor blueColor]; label2.textColor = [UIColor whiteColor]; label1.numberOfLines = 0; label2.numberOfLines = 0; label1.attributedText = text1; label2.attributedText = text2; UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; imageView.frame = CGRectMake(margin + width, margin + height, image.size.width, image.size.height); [self.view addSubview:imageView]; } @end 

…将其放在“单一视图应用程序”的默认视图控制器中。 (您可以选择自己的图像。)

它实际上与NSTextAttachment无关。 就像到目前为止发布的iOS 7中一样,UILabel并不擅长绘制属性字符串。 带有一些下划线和居中段落样式的简单属性字符串将在UILabel中显示空白或部分空白; 相同的属性字符串在UITextView中绘制正常。

因此,现在的一个解决方案是:使用UITextView代替。 这实际上是一个非常好的解决方案,因为在iOS 7中,UITextView只是Text Kit堆栈的包装器。 因此它以直接的方式绘制属性字符串。 它在以前的iOS版本中与Web Kit的底层关系并没有受到任何阻碍。

另一方面,我也找到了这个UILabel bug的解决方法; 你必须弄乱标签和字符串的行数,以便将文本卡在标签的顶部:请参阅我的答案 – https://stackoverflow.com/a/19409962/341994

或者你可以等待Apple修复bug并保持手指交叉。 编辑:在iOS 7.1中,似乎将修复错误,不需要解决方法。

这似乎是UILabel一个错误。 当使用UITextView而不是UILabel时,相同的代码工作正常( UITextView的默认字体大小不同,所以我在不同的高度测试它)。

您是否尝试使用boundingRectWithSize方法获取文本的实际高度:

 NSAttributedString *text; CGFloat width = 200; CGRect rect = [text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil]; CGFloat height = rect.size.height; 

我找到了这个bug的另一个解决方法,这与我以前的答案有很大不同,我将其作为另一个答案提供:让标签设置自己的高度。

在这段代码中,我从具有固定宽度约束的标签中删除高度约束,并将其替换为大于高度的约束(我确信还有其他方法可以实现相同的结果):

 [self.lab removeConstraint:self.labelHeight]; [self.lab addConstraint: [NSLayoutConstraint constraintWithItem:self.lab attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:0 multiplier:1 constant:20]]; 

那个标签正确显示我扔给它的每个属性字符串! 当然,你失去了字符串的自动垂直居中,但这是bug的全部来源,所以失去它并不是那么可怕。