Динамически изменять высоту просмотра с помощью Core Text - PullRequest
3 голосов
/ 06 октября 2011

У меня есть вид, в котором я хочу нарисовать текст с помощью Text Core (на iPad). Когда текст вырос, я бы хотел увеличить высоту просмотра, но не знаю, как рассчитать необходимую высоту рамки. Я использую его для рисования текста в методе drawRect:

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)currentTexts);
    CGMutablePathRef textPath = CGPathCreateMutable();
    CGRect textRect = CGRectMake(PADDING, PADDING, self.frame.size.width - 2 * PADDING, self.frame.size.height - 2 * PADDING);
    CGPathAddRect(textPath, NULL, textRect);
    CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), textPath, NULL);

    CTFrameDraw(textFrame, context);

    CFRelease(textFrame);
    CGPathRelease(textPath);
    CFRelease(framesetter);

Я попытался получить высоту текста с помощью sizeWithFont, а также:

- (CGSize) measureFrame: (CTFrameRef) frame
{
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));
}

Я использую это для создания атрибутной строки:

CTParagraphStyleSetting setting[1] = {
    {kCTParagraphStyleSpecifierMinimumLineSpacing, sizeof(CGFloat), &minimumLineSpacing}
};

CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(setting, 1);

NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys:
                      (id)textColor.CGColor, kCTForegroundColorAttributeName,
                      (id)currentFont, kCTFontAttributeName, 
                      (id)paragraphStyle, kCTParagraphStyleAttributeName,
                      nil];

Когда я использую sizeWithFont, в начале все в порядке, но когда в тексте больше строк, рамка больше и больше текста, и я хочу, чтобы она вписывалась точно в текст. Как я могу это сделать?

1 Ответ

1 голос
/ 01 января 2012

Чтобы рассчитать высоту текста, вы пытались использовать CTFramesetterSuggestFrameSizeWithConstraints?

http://foobarpig.com/iphone/using-ctframesettersuggestframesizewithconstraints-and-sizewithfont-to-calculate-text-height.html

...