5

CoreText を介して NSString を描画しているカスタム UIView があります。

- (NSMutableAttributedString *)getAttributedString : (NSString *)displayText {
string = [[NSMutableAttributedString alloc]
                                     initWithString:displayText];

helvetica = CTFontCreateWithName(CFSTR("Helvetica"), 20.0, NULL);

[string addAttribute:(id)kCTFontAttributeName
               value:(__bridge id)helvetica
               range:NSMakeRange(0, [string length])];

return string;
}

- (void)drawRect:(CGRect)rect
{

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(
                                                                       (__bridge CFAttributedStringRef)string);
// left column form
leftColumnPath = CGPathCreateMutable();
CGPathAddRect(leftColumnPath, NULL,
              CGRectMake(0, 0,
                         self.bounds.size.width,
                         self.bounds.size.height));

// left column frame
textleftFrame = CTFramesetterCreateFrame(framesetter,
                                     CFRangeMake(0, 0),
                                     leftColumnPath, NULL);

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    // right column form
    rightColumnPath = CGPathCreateMutable();
    CGPathAddRect(rightColumnPath, NULL,
                  CGRectMake(self.bounds.size.width/2.0, 0,
                             self.bounds.size.width/2.0,
                             self.bounds.size.height));

    NSInteger rightColumStart = CTFrameGetVisibleStringRange(textleftFrame).length;

    // right column frame
    textrightFrame = CTFramesetterCreateFrame(framesetter,
                                          CFRangeMake(rightColumStart, 0),
                                          rightColumnPath,
                                          NULL);
}

// flip the coordinate system
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

// draw
CTFrameDraw(textleftFrame, context);
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    CTFrameDraw(textrightFrame, context);
}

// cleanup
CFRelease(textleftFrame);
CGPathRelease(leftColumnPath);
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    CFRelease(textrightFrame);
    CGPathRelease(rightColumnPath);
}
CFRelease(framesetter);
CFRelease(helvetica);
CFRelease(helveticaBold);
}

別のクラスでは、boundingRectWithSize を使用して、テキストを表示するビューの長さを計算しようとしています (その後、これに一致するように UIScrollView を設定します)。

NSMutableAttributedString * attributedString = [textView getAttributedString:text];

    // Code here for iOS 7.0 - sizeWithFont is deprecated.
    CGRect textBoxSize = [attributedString boundingRectWithSize:CGSizeMake(315.f, CGFLOAT_MAX) options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil];

    textView.frame = CGRectMake(textView.frame.origin.x, pictureSpace, textBoxSize.size.width, textBoxSize.size.height);

getAttributedString メソッドは上にあります。問題は、textView の高さが少し短すぎるため、テキストの最後の行が切り取られることです。誰が何が間違っているのか提案できますか?

また、余談ですが、boundingRectWithSize のサイズを 320 ではなく 315 (画面の幅よりわずかに短い) にする必要があるのはなぜですか? 320 では、textView は画面に対して少し幅が広すぎます。

編集 - これは特定のフォントでのみ発生するようです。たとえば、Verdana は正常に動作します。これがグリフと関係があるかどうか、より知識のある人は知っていますか?

ありがとう !

4

2 に答える 2

3

MMProgressHudプロジェクトでは、さまざまなコンポーネントのさまざまなサイズがboundingRectWithSize:options:context:メソッドを使用して計算され、フォントの使用に問題がありましたが、HelveticaNeue-Lightフォントを使用している人はいませんでしたVerdana

NSString に新しいカテゴリを作成して、Core-Text を使用して独自の測定方法を作成し、通常の動作をさせました。これは、この投稿とこの投稿に触発されています。

#import "NSString+CustomMetrics.h"
#import<CoreText/CoreText.h>
@implementation NSString (CustomMetrics)

- (CGSize) boundingRectWithSize:(CGSize) bounds andFont:(UIFont*) uiFont
{

    CTFontRef ctFont = CTFontCreateWithName((CFStringRef) uiFont.fontName,uiFont.pointSize, NULL);

    CGFloat ascent = CTFontGetAscent(ctFont);
    CGFloat descent = CTFontGetDescent(ctFont);
    CGFloat leading = CTFontGetLeading(ctFont);

    if (leading < 0)
        leading = 0;

    leading = floor (leading + 0.5);

    CGFloat lineHeight = floor (ascent + 0.5) + floor (descent + 0.5) + leading;
    CGFloat  ascenderDelta = 0;
    if (leading > 0)
        ascenderDelta = 0;
    else
        ascenderDelta = floor (0.2 * lineHeight + 0.5);

    CGFloat defaultLineHeight = lineHeight + ascenderDelta;

    CTParagraphStyleSetting paragraphSettings[1] = { {kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof (CGFloat), &defaultLineHeight} };

    CTParagraphStyleRef  paragraphStyle = CTParagraphStyleCreate(paragraphSettings, 1);
    CFRange textRange = CFRangeMake(0, self.length);

    //  Create an empty mutable string big enough to hold our test
    CFMutableAttributedStringRef string = CFAttributedStringCreateMutable(kCFAllocatorDefault, self.length);

    //  Inject our text into it
    CFAttributedStringReplaceString(string, CFRangeMake(0, 0), (CFStringRef) self);

    //  Apply our font and line spacing attributes over the span
    CFAttributedStringSetAttribute(string, textRange, kCTFontAttributeName, ctFont);
    CFAttributedStringSetAttribute(string, textRange, kCTParagraphStyleAttributeName, paragraphStyle);

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(string);
    CFRange fitRange;

    CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, textRange, NULL, bounds, &fitRange);

    CFRelease(framesetter);
    CFRelease(string);
    CFRelease(ctFont);

    return frameSize;

}
@end
于 2014-02-13T16:34:10.050 に答える
0

ああ - CoreText は、boundingBox メソッドとは異なる方法でテキストを配置しているようです: Core Text では行間隔はどのように機能しますか? (そして、なぜ NSLayoutManager と違うのですか?)

于 2013-09-30T15:20:24.787 に答える