20

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

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

尝试在 a 内并排放置多个 UILabelUITableViewCell并让标签随单元格高度(垂直)增长时,会出现此问题。

谁能解释为什么会这样?有谁知道不涉及使 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

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

4

4 回答 4

21

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

因此,目前的一种解决方案是:改用 UITextView。这实际上是一个很好的解决方案,因为在 iOS 7 中,UITextView 只是 Text Kit 堆栈的包装器。所以它以一种直接的方式绘制属性字符串。它不受以前 iOS 版本中与 Web Kit 的底层关系的阻碍。

另一方面,我也找到了这个 UILabel 错误的解决方法;您必须摆弄标签和字符串的行数,以便将文本卡在标签顶部:在此处查看我的答案-https: //stackoverflow.com/a/19409962/341994

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

于 2013-10-16T22:52:15.523 回答
2

这似乎是UILabel. 使用相同的代码UITextView代替UILabel(UITextView的默认字体大小不同,因此我在不同的高度上对其进行了测试) 时可以正常工作。

于 2013-10-12T10:33:12.997 回答
1

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

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

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

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

于 2013-10-23T14:54:24.733 回答
0

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

NSAttributedString *text;
CGFloat width = 200;
CGRect rect = [text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil];
CGFloat height = rect.size.height;
于 2013-10-15T12:01:01.410 回答