2010-07-19 2 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

Это не работает для некоторых шрифтов. Просто протестирован с использованием шрифта AcademEngravedLetPlain, и шрифт не нарисован – Coolant

+0

Но мне удалось его обработать, установив высоту прямоугольного размера как высоту исходной границы, а не высоту ограничивающего диапазона – Coolant

+0

и она работает для нескольких строк ??? – MatterGoal

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); 
Смежные вопросы