2014-02-21 18 views

回答

4

具體使用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; 
} 
+0

嗨,@Stefan。我曾經有過類似的問題(http://stackoverflow.com/questions/21751738/ios-finding-correct-font-size-to-fit-in-a-uilabel-depending-on-its-size)posted在此之前,我認爲它與這個密切相關。但是我不是想找到最後一個字母的邊界框,而是在給定特定字體和大小的情況下,在一行中查找字母的大小,並使用CoreText均勻地在一行上將它們分隔(或「UILabel」)。看看那裏,當你有時間。提前致謝。 – Unheilig

相關問題