12

我有一个UILabel字符串'LA'。我也有一个CATextLayer具有相同字符的 anNSAttributedString分配给它的string属性。中的字距调整UILabelCATextLayer. 这是代码。

- (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];
}

这是结果的图像

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

4

3 回答 3

3

UIKit 通常使用 WebKit 进行文本渲染(如本崩溃日志中所示),很可能是出于性能原因。如果您真的需要超精度,那么可以使用一些自定义UILabel重新实现CoreText作为其后端。

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

于 2012-10-06T18:36:52.230 回答
1

您应该将属性添加到您的 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);
于 2013-03-04T06:44:05.800 回答
0

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

于 2012-05-29T05:37:22.130 回答