我有一个UILabel
字符串'LA'。我还有CATextLayer
个NSAttributedString
分配给其string
媒体资源的相同字符。 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
示例中做错了什么?
答案 0 :(得分:3)
UIKit通常使用WebKit进行文本渲染(在this crash log)中可见),最有可能出于性能原因。如果您确实需要超精度,那么有一些custom UILabel
reimplementations使用CoreText
作为它的后端。
修改强>
从iOS7开始,这不再是真的,因为UILabel
使用TextKit进行渲染,它也基于CoreText。
答案 1 :(得分: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);
答案 2 :(得分:0)
与使用UIKit绘制字符串相比,Core Text
非常不同,可能是因为它来自Core Foundation
而不是AppKit
或UIKit
。我确实理解您使用标签在字符串上执行度量标准的要求。对我来说,唯一的解决方案是匹配属性字符串中UILabel
的字距,遗憾的是我不知道确切的值,但您可以使用此属性更改该值kCTKernAttributeName
。你也应该注意可能不一样的联运
将该值强制为匹配的字距调整,您可以拥有正确的行为。如果您想要相反(匹配CT字距调整),您应该进行一些数学运算,稍后应用于标签UIEdgeInset
以计算正确的标签。
希望这会有所帮助。