【问题标题】:UILabel default kerning different from CATextLayerUILabel 默认字距与 CATextLayer 不同
【发布时间】:2012-05-15 15:59:57
【问题描述】:

我有一个带有字符串“LA”的UILabel。我还有一个CATextLayer,在分配给其string 属性的NSAttributedString 中具有相同的字符。 UILabel 中的字距调整与CATextLayer 明显不同。这是代码。

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 
    // UILabel
    //
    UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 280, 100)];
    label1.text = @"LA";
    label1.backgroundColor = [UIColor clearColor];
    label1.font = [UIFont fontWithName:@"Futura" size:90.0];
    [self.view addSubview:label1];

    //
    // CATextLayer
    //
    UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectMake(20, 130, 280, 100)];
    label2.backgroundColor = [UIColor clearColor];
    CATextLayer *textLayer = [[CATextLayer alloc] init];
    textLayer.frame = label2.layer.bounds;
    textLayer.contentsScale = [[UIScreen mainScreen] scale];
    [label2.layer addSublayer:textLayer];
    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"LA"];
    CTFontRef aFont = CTFontCreateWithName((__bridge CFStringRef)@"Futura", 90.0, NULL);
    [string addAttribute:(NSString*)kCTFontAttributeName value:(__bridge id)aFont range:NSMakeRange(0, [string length])];
    textLayer.string = string;
    [self.view addSubview:label2];
}

这是an image 的结果。

为什么这两种方法之间的字距不同,我在CATextLayer 示例中做错了什么?

【问题讨论】:

  • 你找到这个问题的解决方案了吗?

标签: iphone ios uikit core-text


【解决方案1】:

UIKit 通常使用 WebKit 进行文本渲染(如在 this crash log) 中可见,很可能是出于性能原因。如果您真的需要超精度,那么有一些 custom UILabel reimplementations 使用 CoreText 作为其后端。

编辑: 从 iOS7 开始,这不再适用,因为 UILabel 使用 TextKit 进行渲染,它也基于 CoreText。

【讨论】:

    【解决方案2】:

    你应该为你的 NSMutableAttributedString 添加属性。

    对于字距调整:

        CGFloat characterspacing = 10.0f;
        CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&characterspacing);
        [string addAttribute:(id)kCTKernAttributeName value:(id)num range:NSMakeRange(0 , [string length])];
        CFRelease(num);
    

    如果还需要行距,或者设置 LineBreadMode:

        CTLineBreakMode linebreak = kCTLineBreakByCharWrapping;
        CTParagraphStyleSetting linebreakStyle;
        linebreakStyle.spec = kCTParagraphStyleSpecifierLineBreakMode;
        linebreakStyle.valueSize = sizeof(linebreak);
        linebreakStyle.value = &linebreak;
    
        CTParagraphStyleSetting lineSpaceStyle;
        CGFloat linespacing = self.linesSpacing;
        lineSpaceStyle.spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;
        lineSpaceStyle.valueSize = sizeof(linespacing);
        lineSpaceStyle.value =&linespacing;
        CTParagraphStyleSetting settings[ ] ={linebreakStyle,lineSpaceStyle};
        CTParagraphStyleRef style = CTParagraphStyleCreate(settings ,2);
        [string addAttribute:(id)kCTParagraphStyleAttributeName value:(id)style range:NSMakeRange(0 , [string length])];
        CFRelease(style);
    

    最后,你可能需要计算一下你的字距、行距和 LineBreakMode 的行数(linenum):

    CTFramesetterRef myframesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);
    CGMutablePathRef leftColumnPath = CGPathCreateMutable();
    CGPathAddRect(leftColumnPath, NULL ,CGRectMake(0 , 0 , Lable.frame.size.width, MAXFLOAT));
    CTFrameRef leftFrame = CTFramesetterCreateFrame(myframesetter,CFRangeMake(0, 0), leftColumnPath , NULL);
    CFArrayRef lines = CTFrameGetLines(leftFrame);
    linenum = (int)CFArrayGetCount(lines);
    CFRelease(myframesetter);
    CFRelease(leftFrame);
    CGPathRelease(leftColumnPath);
    

    【讨论】:

      【解决方案3】:

      Core Text 与使用 UIKit 绘制字符串相比确实不同,可能是因为它来自 Core Foundation 而不是 AppKitUIKit。我确实理解您对使用标签在字符串上执行度量标准的要求。对我来说唯一的解决方案是匹配属性字符串中UILabel 的字距,不幸的是我不知道确切的值,但您可以使用此属性来更改该值kCTKernAttributeName。您还应该注意可能不一样的联运。
      将该值强制为匹配的字距调整,您可能会有正确的行为。如果你想要相反的(匹配 CT 字距调整),你应该做一些数学运算,然后将标签应用到 UIEdgeInset 以计算正确的标签。
      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2011-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-20
        • 2019-05-02
        • 2019-09-27
        • 2020-06-03
        • 1970-01-01
        相关资源
        最近更新 更多