2010-07-19 98 views
8

An image clarifying things與核心文本垂直對齊?

如何更改CTFramesetter框架中文本的垂直對齊方式?我希望我的文字處於中間位置,而不是在頂部。我正在使用Core Text框架。有段的設置改變水平對齊但不垂直。

回答

7

終於找到它了...

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

這並不適用於某些字體。剛剛使用AcademyEngravedLetPlain字體進行了測試,並且字體沒有繪製 – Coolant 2012-12-04 23:59:03

+0

但我已經設法通過將rect尺寸高度設置爲原始邊界高度,而不是邊界框高度 – Coolant 2012-12-05 01:26:14

+0

並且它對於多行工作? – MatterGoal 2013-01-08 18:14:00

4

感謝尼克,這是一個偉大的片段。

只是擴大上,如果你做的頂部,中部和底部對齊枚舉,例如,你可以做到這一點,像這樣:

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

這說明了一個事實,即多字體和樣式可以在一幀中使用(計算高度和文本的寬度,看在if(index == lastLineIndex)塊上看到的高度被計算):

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

參考:斯科特·湯普森(http://lists.apple.com/archives/quartz-dev/2008/Mar/msg00079.html

3

您可以使用[NSString boundingRectWithSize:options:attributes:context:]來獲取字符串邊界框的矩形,這也允許使用多行文本。 在你的畫文本的方法,請執行下列操作(RECT是要繪製文本的矩形):

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