2012-05-07 11 views
12

Tôi có một số UILabel với chuỗi 'LA'. Tôi cũng có một số CATextLayer có cùng các ký tự trong một số NSAttributedString được gán cho thuộc tính string của nó. Các kerning trong UILabel là đáng chú ý khác nhau từ CATextLayer. Đây là mã.Mặc định nhãn mặc định khác với 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]; 
} 

Đây là an image kết quả.

Tại sao sự khác biệt giữa hai phương pháp này và tôi đang làm gì sai trong ví dụ CATextLayer?

+0

bạn có tìm thấy giải pháp cho câu hỏi này không? – haroldcampbell

Trả lời

3

UIKit thường sử dụng WebKit cho việc vẽ chữ của nó (như được nhìn thấy trong this crash log), rất có thể vì lý do hiệu suất. Nếu bạn thực sự cần siêu chính xác sau đó có một số custom UILabel reimplementations sử dụng CoreText như nó back-end.

EDIT : Tính đến iOS7 này không còn đúng từ UILabel sử dụng TextKit cho dựng hình của nó mà là dựa trên CoreText cũng

0

Vâng Core Text thực sự khác nhau khi so sánh với chuỗi vẽ bằng UIKit, có lẽ vì nó xuất phát từ Core Foundation và không AppKit hoặc UIKit. Tôi hiểu các yêu cầu của bạn để sử dụng nhãn để thực hiện các số liệu công việc khó khăn trên một chuỗi. Giải pháp duy nhất cho tôi là để phù hợp với kerning của UILabel trong chuỗi được phân bổ, tiếc là tôi không biết giá trị chính xác nhưng bạn có thể sử dụng thuộc tính này để thay đổi giá trị đó kCTKernAttributeName. Bạn cũng nên chú ý đến đường giao nhau có thể không giống nhau.
Buộc giá trị đó cho kerning phù hợp bạn có thể có hành vi đúng. Nếu bạn muốn đối diện (khớp với CT sành điệu) bạn nên làm một số toán học sau đó áp dụng cho nhãn một UIEdgeInset để tính toán nhãn chính xác.
Hy vọng điều này sẽ hữu ích.

1

bạn nên thêm thuộc tính để NSMutableAttributedString bạn

..

Đối với kerning:

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

Nếu bạn cũng cần khoảng cách dòng, hoặc thiết lập 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); 

Cuối cùng, bạn có thể cần tính toán số lượng dòng (lineNum) về kerning của bạn , giãn cách dòng và LineBreakMode:

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);