ibireme / YYText

Powerful text framework for iOS to display and edit rich text.
MIT License
8.86k stars 1.7k forks source link

YYLabel在计算省略(...)位置的时候,计算错误 #268

Closed starFelix closed 8 years ago

starFelix commented 8 years ago

代码如下:

    NSMutableAttributedString *text = [NSMutableAttributedString new];      
    UIFont *font = [UIFont systemFontOfSize:14];    
    NSArray *textArray = @[@"干性皮肤",@"黑眼圈",@"王菲的化妆",@""];    
    self.topTipLabel.font = font;    
    for (NSString *subText in textArray) {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        [button setTitle:subText forState:UIControlStateNormal];
        [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        [button.titleLabel setFont:font];
        UIImage *image = [UIImage imageForKey:@"first_inboxcirclevcheck.png"];
        [button setImage:image forState:UIControlStateNormal];
        [button sizeToFit];
        NSMutableAttributedString *attachText = [NSMutableAttributedString yy_attachmentStringWithContent:button contentMode:UIViewContentModeCenter attachmentSize:button.size alignToFont:font alignment:YYTextVerticalAlignmentCenter];
        [text appendAttributedString:attachText];
    }
    self.topTipLabel.attributedText = text;

如果数组中只有三个,会显示完整,效果如下

a

如果数组中多出一个,则效果如下:

b

可以看到,明明是有空间显示第三个,但是结果第三个也被隐藏了,非常奇怪。

starFelix commented 8 years ago

我用demo里面的工程,把switch换成button,在拖拽中一样很明显能发现这个bug。

ibireme commented 8 years ago

button 作为一个完整的元素,不能被截断,如果排版放不下那会被裁剪掉。 这里当一行放不下所有文本时,会在结尾放一个 ... 符号,而这个符号也会占据一定的空间,这样 button 就被挤掉了。这不算是 bug,而是计算方法只能是这样。。

想象一下:Label 的视图宽度刚刚够显示那 3 个 button 的,但这时候又加了第 4 个 button,这时候这个 Label 根据配置来说就必须在结尾显示一个 ... 来提示用户这行文本没有显示全,视图这时已经没有多余空间了,这只能把第 3 个 button 拿掉,换成 ...

starFelix commented 8 years ago

@ibireme 我计算过的,放下三个button加...是足够空间的,并非仅仅只能放三个button。从图中也可以看出还是剩余不少空间的。除非...所占空间远比实际要大。

starFelix commented 8 years ago

并且我在用demo里面那个拖拽试验的时候也发现了,只要空间不够显示,被隐藏了的一定会是两个。

starFelix commented 8 years ago

我反复调试代码,发现YYTextLayout的逻辑有点问题: a 这个地方的cgPath是根据可显示区域的rect生成的,跑完这部分代码后,由于实际内容超出可显示区域,ctFrames其实已经少了一个,最后一个被删除。 b 到这里,自然就会判断出没有完全显示,需要显示...c 问题代码在这里,正如前面所说,最后一个其实已经被删除了,而这部分代码会再删一个。于是原本可以显示三个button的,现在变成了两个。而我把阴影部分的代码删除后,显示出来的结果便是正确的。实际在代码上就可以看到另一个问题,当用户有自定义...时,并没有删除操作,这个行为和使用默认...的情况不一致。

@ibireme

starFelix commented 8 years ago
d

可以看到空间是足够放三个button加...的。

ibireme commented 8 years ago

看了下这段代码,是有点问题,但应该不是你描述那样(阴影部分只是用于创建一个和最后字符同属性的 attrs)。。

试试在

[attrs removeObjectForKey:YYTextAttachmentAttributeName];

这行后面再加一行看看

[attrs removeObjectForKey:(id)kCTRunDelegateAttributeName];

我觉得是把最后一个字符(button)的 RunDelegate 带入了 ... 导致的。。

如果这样没问题的话,我 push 一下代码,再多加些额外的处理。

starFelix commented 8 years ago

@ibireme 按你说的添加了这行代码是ok的。 另外我有个疑惑,为啥...的默认字体颜色不是跟着label的设置,并且乘以0.9是什么作用?

ibireme commented 8 years ago

颜色会随着最后一个字符的颜色走吧(这里是 attachment,而 attachment 是没有颜色的,默认黑色)。0.9 最初好像是为了避免什么字体高度还是宽度的溢出?不过现在看看应该没必要了。。

starFelix commented 8 years ago

那我觉得,...应该跟着最后一个文本走,如果没有文本都是attachment就用label的设置。

ibireme commented 8 years ago

有 attachment 的地方,并不一定表示那块儿没有文本啊。。attachment 本身也是有各种属性的,这个不能忽略啊。另外,label 的设置,实际上也只是对 attributedString 属性的封装。

你可以在创建整个文本后,用 text.yy_color 来设置整个文本的颜色。