3
我有一個NSAttributedString
,繪製整個字符串的矩形,我想要得到最後一個字符的矩形,就像下面的圖像一樣,如何使用Core文字?如何獲得使用核心文本的最後一個字符的矩形
我有一個NSAttributedString
,繪製整個字符串的矩形,我想要得到最後一個字符的矩形,就像下面的圖像一樣,如何使用Core文字?如何獲得使用核心文本的最後一個字符的矩形
具體使用CoreText,這裏應該工作(與代碼的一些註釋解釋這是怎麼回事)功能:
- (CGRect)lastCharacterRectForAttributedString:(NSAttributedString *)attributedString drawingRect:(CGRect)drawingRect
{
// Start by creating a CTFrameRef using the attributed string and rect.
CTFrameRef textFrame = NULL;
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attributedString));
CGPathRef drawingPath = CGPathCreateWithRect(drawingRect, NULL);
textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attributedString length]), drawingPath, NULL);
CFRelease(framesetter);
CFRelease(drawingPath);
// Line origins can be obtained from the CTFrameRef. Get the final one.
CGPoint finalLineOrigin;
CFArrayRef lines = CTFrameGetLines(textFrame);
if (CFArrayGetCount(lines) == 0) { // Safety check
CFRelease(textFrame);
return CGRectNull;
}
const CFIndex finalLineIdx = CFArrayGetCount(lines) - 1;
CTFrameGetLineOrigins(textFrame, CFRangeMake(finalLineIdx, 1), &finalLineOrigin);
// Get the glyph runs from the final line. Get the last glyph position from the final run.
CGPoint glyphPosition;
CFArrayRef runs = CTLineGetGlyphRuns(CFArrayGetValueAtIndex(lines, finalLineIdx));
if (CFArrayGetCount(runs) == 0) { // Safety check
CFRelease(textFrame);
return CGRectNull;
}
CTRunRef finalRun = CFArrayGetValueAtIndex(runs, CFArrayGetCount(runs) - 1);
if (CTRunGetGlyphCount(finalRun) == 0) { // Safety check
CFRelease(textFrame);
return CGRectNull;
}
const CFIndex lastGlyphIdx = CTRunGetGlyphCount(finalRun) - 1;
CTRunGetPositions(finalRun, CFRangeMake(lastGlyphIdx, 1), &glyphPosition);
// The bounding box of the glyph itself is extracted from the font.
CGRect glyphBounds;
CFDictionaryRef runAttributes = CTRunGetAttributes(finalRun);
CTFontRef font = CFDictionaryGetValue(runAttributes, NSFontAttributeName);
CGGlyph glyph;
CTRunGetGlyphs(finalRun, CFRangeMake(lastGlyphIdx, 1), &glyph);
CTFontGetBoundingRectsForGlyphs(font, kCTFontDefaultOrientation, &glyph, &glyphBounds, 1);
// Option 1 - The rect you've drawn in your question isn't tight to the final character; it looks approximately the height of the line. If that's what you're after:
CGRect lineBounds = CTLineGetBoundsWithOptions(CFArrayGetValueAtIndex(lines, finalLineIdx), 0);
CGRect desiredRect = CGRectMake(
CGRectGetMinX(drawingRect) + finalLineOrigin.x + glyphPosition.x + CGRectGetMinX(glyphBounds),
CGRectGetMinY(drawingRect) + (CGRectGetHeight(drawingRect) - (finalLineOrigin.y + CGRectGetMaxY(lineBounds))),
CGRectGetWidth(glyphBounds),
CGRectGetHeight(lineBounds)
);
// Option 2 - If you want a rect that closely bounds the final character, use this:
/*
CGRect desiredRect = CGRectMake(
CGRectGetMinX(drawingRect) + finalLineOrigin.x + glyphPosition.x + CGRectGetMinX(glyphBounds),
CGRectGetMinY(drawingRect) + (CGRectGetHeight(drawingRect) - (finalLineOrigin.y + glyphPosition.y + CGRectGetMaxY(glyphBounds))),
CGRectGetWidth(glyphBounds),
CGRectGetHeight(glyphBounds)
);
*/
CFRelease(textFrame);
return desiredRect;
}
嗨,@Stefan。我曾經有過類似的問題(http://stackoverflow.com/questions/21751738/ios-finding-correct-font-size-to-fit-in-a-uilabel-depending-on-its-size)posted在此之前,我認爲它與這個密切相關。但是我不是想找到最後一個字母的邊界框,而是在給定特定字體和大小的情況下,在一行中查找字母的大小,並使用CoreText均勻地在一行上將它們分隔(或「UILabel」)。看看那裏,當你有時間。提前致謝。 – Unheilig