2010-07-19 4 views
8

An image clarifying thingsVertikale Ausrichtung mit Core Text?

Wie ändere ich die vertikale Ausrichtung des Textes in einem CTFramesetter Rahmen? Ich möchte, dass mein Text in der Mitte ist anstatt in der oben. Ich verwende Core Text Framework. Es gibt eine Einstellung des Absatzes, um die horizontale Ausrichtung zu ändern, aber nicht vertikal.

Antwort

7

dachte es schließlich heraus ...

CGRect boundingBox = CTFontGetBoundingBox(font); 

//Get the position on the y axis 
float midHeight = self.frame.size.height/2; 
midHeight -= boundingBox.size.height/2; 

CGPathAddRect(path, NULL, CGRectMake(0, midHeight, self.frame.size.width, boundingBox.size.height)); 
+0

Dies funktioniert nicht für einige Schriftarten. Gerade getestet mit der AcademyEngravedLetPlain Schriftart, und die Schrift wird nicht gezeichnet – Coolant

+0

Aber ich habe es geschafft, es auszuarbeiten, indem Sie die rect Größe Höhe als die ursprüngliche Grenzen Höhe, nicht die BoundingBox Höhe – Coolant

+0

und funktioniert es für mehrere Zeilen? – MatterGoal

4

Dank Nick, die ein großer Schnipsel war.

einfach auf die Erweiterung, wenn Ihr Top tun, mittlere und untere Ausrichtung mit einem Enum, zum Beispiel könnten Sie es wie so tun:

if (VerticalAlignmentTop == currentTextAlignment) { 
    CGPathAddRect(path, NULL, rect); // Draw normally (top) 
} 
else if (VerticalAlignmentMiddle == currentTextAlignment) { 
    CGRect boundingBox = CTFontGetBoundingBox(fontRef); 

    //Get the position on the y axis (middle) 
    float midHeight = rect.size.height/2; 
    midHeight -= boundingBox.size.height/2; 

    CGPathAddRect(path, NULL, CGRectMake(0, midHeight, rect.size.width, boundingBox.size.height)); 
} 
else { 
    CGRect boundingBox = CTFontGetBoundingBox(fontRef); 

    CGPathAddRect(path, NULL, CGRectMake(0, 0, rect.size.width, boundingBox.size.height)); 
} 
1

Dies die Tatsache erklärt, dass mehrere Schriftarten und Stile können in einem Rahmen verwendet werden (berechnet Höhe und Breite des Textes, Blick in den if(index == lastLineIndex) Block, um zu sehen, wo die Höhe berechnet wird):

- (CGSize) measureFrame: (CTFrameRef) frame forContext: (CGContext *) cgContext 
{ 
    CGPathRef framePath = CTFrameGetPath(frame); 
    CGRect frameRect = CGPathGetBoundingBox(framePath); 

    CFArrayRef lines = CTFrameGetLines(frame); 
    CFIndex numLines = CFArrayGetCount(lines); 

    CGFloat maxWidth = 0; 
    CGFloat textHeight = 0; 

    // Now run through each line determining the maximum width of all the lines. 
    // We special case the last line of text. While we've got it's descent handy, 
    // we'll use it to calculate the typographic height of the text as well. 

    CFIndex lastLineIndex = numLines - 1; 
    for(CFIndex index = 0; index < numLines; index++) 
    { 
     CGFloat ascent, descent, leading, width; 
     CTLineRef line = (CTLineRef) CFArrayGetValueAtIndex(lines, index); 
     width = CTLineGetTypographicBounds(line, &ascent,  &descent, &leading); 

     if(width > maxWidth) 
     { 
      maxWidth = width; 
     } 

     if(index == lastLineIndex) 
     { 
      // Get the origin of the last line. We add the descent to this 
      // (below) to get the bottom edge of the last line of text. 

      CGPoint lastLineOrigin; 
      CTFrameGetLineOrigins(frame, CFRangeMake(lastLineIndex, 1), &lastLineOrigin); 

      // The height needed to draw the text is from the bottom of the last line 
      // to the top of the frame. 

      textHeight =  CGRectGetMaxY(frameRect) - lastLineOrigin.y + descent; 
     } 
    } 

    // For some text the exact typographic bounds is a fraction of a point too 
    // small to fit the text when it is put into a context. We go ahead and round 
    // the returned drawing area up to the nearest point.  This takes care of the 
    // discrepencies. 

    return CGSizeMake(ceil(maxWidth), ceil(textHeight)); 
} 

Referenz: Scott Thompson (http://lists.apple.com/archives/quartz-dev/2008/Mar/msg00079.html)

3

Sie können [NSString boundingRectWithSize: options: attributes: context:] verwenden, um das Rechteck der Begrenzungsbox Ihrer Zeichenkette zu erhalten, das auch mehrzeiligen Text zulässt. In Ihrem Draw Text Verfahren Sie wie folgt vor (RECT das Rechteck ist, wo Sie den Text zeichnen möchten):

// get the graphics context 
CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSaveGState(context); 

// flip the context coordinate 
CGContextTranslateCTM(context, 0.0f, 2*RECT.origin.y+RECT.size.height); 
CGContextScaleCTM(context, 1.0f, -1.0f); 

// Set the text matrix. 
CGContextSetTextMatrix(context, CGAffineTransformIdentity); 

// set text horizontal alignment 
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; 
paragraphStyle.alignment = NSTextAlignmentCenter; 

NSDictionary *attributes = @{NSParagraphStyleAttributeName:paragraphStyle, NSFontAttributeName:YOUR_FONT, NSForegroundColorAttributeName:TEXT_COLOR}; 
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:YOUR_TEXT attributes:attributes]; 

CGMutablePathRef path = CGPathCreateMutable(); 

// set text vertical alignment 
CGSize textSize = [text boundingRectWithSize:RECT.size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size; 
CGPathAddRect(path, NULL, CGRectMake(RECT.origin.x, RECT.origin.y-(RECT.size.height-textSize.height)/2.0f, RECT.size.width, RECT.size.height)); 

CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString); 
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, attrString.length), path, NULL); 
CTFrameDraw(frame, context); 

CFRelease(frame); 
CFRelease(path); 
CFRelease(frameSetter); 

[attrString release]; 
[paragraphStyle release]; 

CGContextRestoreGState(context);