2010-07-19 116 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);