2012-05-07 3 views
12

Ho uno UILabel con la stringa "LA". Ho anche un CATextLayer con gli stessi caratteri in un NSAttributedString assegnato alla sua proprietà string. La crenatura nello UILabel è notevolmente diversa da CATextLayer. Ecco il codice.Uelabel di crenatura predefinita diversa da 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]; 
} 

Ecco il risultato an image.

Perché il cren è diverso tra questi due metodi e cosa sto sbagliando nell'esempio CATextLayer?

+0

hai trovato una soluzione a questa domanda? – haroldcampbell

risposta

3

UIKit genere utilizza WebKit per il suo rendering del testo (come visibile in this crash log), molto probabilmente per motivi di prestazioni. Se davvero bisogno di super-precisione poi ci sono alcuni custom UILabel reimplementations utilizzando CoreText come il suo back-end.

EDIT : partire iOS7 questo non è più vero in quanto utilizza UILabel TextKit per la sua rappresentazione che si basa su CoreText così

0

Bene Core Text è davvero diversa rispetto alle stringhe di disegno utilizzando UIKit, probabilmente perché viene da Core Foundation e non AppKit o UIKit. Comprendo i tuoi requisiti per utilizzare un'etichetta per eseguire le metriche di lavoro duro su una stringa. L'unica soluzione per me è quella di far corrispondere la crenatura dello UILabel nella stringa attribuita, sfortunatamente non conosco il valore esatto ma puoi usare questa proprietà per cambiare il valore kCTKernAttributeName. Dovresti prestare attenzione anche alla interlinea che potrebbe non essere la stessa.
Forzando quel valore alla crenatura corrispondente si potrebbe avere il comportamento corretto. Se vuoi il contrario (combina CT crenatura) dovresti fare un po 'di matematica e successivamente applicare all'etichetta un UIEdgeInset in matematica l'etichetta corretta.
Spero che questo aiuti.

1

si dovrebbe aggiungere l'attributo al vostro NSMutableAttributedString

..

Per la crenatura:

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

Se hai bisogno anche l'interlinea, o impostare 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); 

Alla fine, potrebbe è necessario calcolare il numero della linea (linenum) sulla tua crenatura , interlinea e 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);