与核心文本垂直对齐?

发布于 2024-09-10 08:53:48 字数 165 浏览 7 评论 0原文

澄清事物的图像

如何更改 CTFramesetter 框架中文本的垂直对齐方式?我希望我的文本位于中间,而不是位于顶部。我正在使用核心文本框架。段落的设置可以更改水平对齐方式,但不能更改垂直对齐方式。

An image clarifying things

How do I change the vertical alignment of the text in a CTFramesetter frame? I want my text to be in the middle instead of being at the top. I am using Core Text framework. There is a setting of the paragraph to change horizontal aligment but not vertical.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

热情消退 2024-09-17 08:53:48

终于想通了...

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

Finally figured it out ...

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));
情释 2024-09-17 08:53:48

谢谢尼克,这是一个很棒的片段。

对此进行扩展,如果您使用枚举进行顶部、中间和底部对齐,例如您可以这样做:

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

Thanks Nick, that was a great snippet.

Just expanding on that, if your doing Top, Middle and Bottom alignment with an enum, for example you could do it like so:

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));  
}
时光沙漏 2024-09-17 08:53:48

您可以使用 [NSStringboundingRectWithSize: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);

You can use [NSString boundingRectWithSize:options:attributes:context:] to get the rectangle of your string's bounding box, which allows multi-line text as well.
In your draw text method, do the following (RECT is the rectangle where you want to draw the text):

// 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);
美男兮 2024-09-17 08:53:48

这说明了一个框架中可以使用多种字体类型和样式的事实(计算文本的高度和宽度,查看 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));
}

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

This accounts for the fact that multiple font types and styles can be used in a frame (calculates both height and width of text, look in the if(index == lastLineIndex) block to see where the height is calculated):

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文