2012-05-07 5 views
12

UILabel에 'LA'라는 문자열이 있습니다. 또한 은 NSAttributedString에 동일한 문자가 있으며 string 속성에 할당되어 있습니다. UILabel의 커닝은 CATextLayer과 현저하게 다릅니다. 여기에 코드가 있습니다.CATextLayer와 다른 UILabel 기본 커닝

- (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 예에서 잘못된 부분이 무엇입니까? AppKit 또는 UIKit을가 Core Foundation에서 유래 아마 때문에, UIKit 사용하여 그리기 문자열 비교하지 않을 때

+0

이 질문에 대한 해결책을 찾았습니까? – haroldcampbell

답변

3

UIKit은 일반적으로, this crash log)에 표시 성능상의 이유로 대부분의 텍스트 렌더링을위한 웹킷을 (사용합니다. 당신이 정말로 초정밀 필요한 경우 백엔드로 CoreText를 사용하여 일부 custom UILabel reimplementations이 있습니다.

편집을 : UILabel뿐만 아니라 CoreText을 기반으로 자사의 렌더링 TextKit을 사용하기 때문에는 iOS7에 현재에서는 더 이상 그렇지 않습니다

0

Core Text 정말 다릅니다. 문자열에 대한 통계 작업을 수행하기 위해 레이블을 사용하기위한 요구 사항을 알고 있습니다. 나를위한 유일한 해결책은 UILabel의 속성 문자열에서 커닝을 일치시키는 것입니다. 불행히도 정확한 값을 알 수는 없지만이 속성을 사용하여 해당 값을 변경할 수 있습니다. kCTKernAttributeName. 동일하지 않을 수도있는 인터 라인에도주의를 기울여야합니다.
일치하는 커닝에 해당 값을 적용하면 올바른 동작을 할 수 있습니다. 반대 (CT 커닝과 일치)를 원할 경우 수학을해야 나중에 올바른 레이블을 산술하기 위해 UIEdgeInset 라벨에 적용해야합니다.
희망이 도움이됩니다.

1
당신은 당신의 NSMutableAttributedString에 속성을 추가해야

.. 당신은 또한 줄 간격, 또는 설정 LineBreadMode 필요한 경우

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

가 :

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

, 당신은 라인 (linenum 인)의 수를 계산해야 할 수 있습니다 당신의 커닝에 대한 커닝에 대한

, 줄 간격 및 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);