Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QMUILabel 的 contentEdgeInsets 在设置 lineBreakMode 的时候有问题 #529

Closed
4 tasks done
Joan-m opened this issue Mar 21, 2019 · 4 comments
Closed
4 tasks done

Comments

@Joan-m
Copy link

Joan-m commented Mar 21, 2019

请填写运行环境

  • 设备:All / iPhone / iPad / 模拟器
  • 系统:iOS 12.1
  • Xcode 版本:10.1
  • QMUI iOS 版本:3.1.2

请描述具体问题

Label.contentEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 0);
Label.lineBreakMode = NSLineBreakByWordWrapping;

在设置 lineBreakMode 后会出现 padding 全部加到了 bottom 的问题

相关截图(断点的堆栈、控制台的 log)

259031553135896_ pic

@zhoon
Copy link
Collaborator

zhoon commented Mar 21, 2019

不需要设置 lineBreakMode 或者设置 nunberOfLines = 0 即可。
至于为什么 NSLineBreakByWordWrapping 会有问题,猜测是命中了系统内部的一些判断,导致 drawTextInRect: 重置 rect 失效。

@ziecho
Copy link
Collaborator

ziecho commented Mar 21, 2019

这个问题需要满足 3 个条件才会出现

  1. label.lineBreakMode 为NSLineBreakByWordWrappingNSLineBreakByCharWrapping
  2. label.numberOfLines == 1
  3. label.contentEdgeInsets.top > 0

通过简单调试猜测,UILabel 符合上述条件时,会忽略 - (void)drawTextInRect:(CGRect)rect 这个方法中 rect 的 y 值进行绘制,内容始终从上面开始,绘制单行,且 centerX = rect.height / 2 (内容居中于高度)

根据上述绘制原理,这里提供一种简单的修复方法

- (void)drawTextInRect:(CGRect)rect {
    CGRect drawInRect = UIEdgeInsetsInsetRect(rect, self.contentEdgeInsets);
    if ((self.lineBreakMode == NSLineBreakByWordWrapping || self.lineBreakMode == NSLineBreakByCharWrapping) && self.numberOfLines == 1 && self.contentEdgeInsets.top > 0) {
        CGSize size = [super sizeThatFits:CGSizeZero];
        drawInRect.size.height = self.contentEdgeInsets.top * 2 + size.height;
    }
    [super drawTextInRect:drawInRect];
}

这里有个顾虑,修改了 height 也不会有什么问题?实测发现在上述条件成立时, UILabel 在最终调用 [NSString drawWithRect:options:attributes:context:] 进行绘制时,传入 rect 的 height 是单行文字的高度,所以应该不会有问题。

另外对于 label.contentEdgeInsets.top < 0 且符合条件 1、2 的情况,修复起来比较麻烦,可能要去 hook UILabel 内部的一些绘制函数,暂时没有什么特别好的办法

@zhoon
Copy link
Collaborator

zhoon commented Mar 21, 2019

一行 label 基本不会设置 NSLineBreakByWordWrapping 这种属性,不过我按照 @ziecho 说的还是做个保护吧

@MoLice
Copy link
Collaborator

MoLice commented Apr 2, 2019

3.1.3 已修复

@MoLice MoLice closed this as completed Apr 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants