2013-09-29 11 views
5

Ich habe eine benutzerdefinierte UIView, die eine NSString über Core zeichnet:NSString boundingRectWithSize Schnitthöhe kurz mit CoreText Framesetter? iOS

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

In einer anderen Klasse ich dann versuche boundingRectWithSize zu verwenden, um zu berechnen, wie lange die Ansicht, um den Text anzuzeigen wird (ich später dann eingestellt a UIScrollView dies entsprechen):

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 Die oben beschriebene Methode ist. Das Problem ist, dass textView in der Höhe etwas zu kurz ist und deshalb die letzte Textzeile abschneidet. Kann jemand vorschlagen, was falsch ist?

Auch, nebenbei bemerkt, warum muss die Größe in BoundingRectWithSize 315 (d. H. Etwas kürzer als die Bildschirmbreite) statt 320 sein, um zu arbeiten? Bei 320 endet der textView etwas zu weit für den Bildschirm.

Bearbeiten - dies scheint nur bei bestimmten Schriftarten passieren - z. B. Verdana funktioniert gut. Weiß jemand, der besser weiß, ob das etwas mit Glyphen zu tun hat?

Danke!

Antwort

0

Ah - es scheint, Core Räume Text unterschiedlich auf die boundingBox Methode: How does line spacing work in Core Text? (and why is it different from NSLayoutManager?)

+0

Wie funktioniert die unterschiedlichen Zeilenabstand in den Code passen die richtige Größe zu bekommen? Ich habe mich auch in den letzten Monaten mit diesem Dimensionierungsproblem (mit Tabellenansichten) herumgeschlagen und dies ist der erste Anhaltspunkt, den ich gesehen habe. – guthook

+1

Versuchen Sie, die Schriftart zu ändern - es scheint nur bei bestimmten Schriftarten zu passieren. – GuybrushThreepwood

+0

Cool, danke für die Info. Ich sah ein wenig mehr und fand das, was helfen könnte: http://Stackoverflow.com/a/18818036/1275947 – guthook

3

Im MMProgressHud Projekt werden die verschiedenen Größen der verschiedenen Komponenten berechnet boundingRectWithSize:options:context: Methode und ich hatte einige Problem mit der HelveticaNeue-Light Schrift aber nicht eines mit der Schriftart Verdana.

Ich habe eine neue Kategorie auf NSString erstellt, um meine eigene Messmethode mit Core-Text zu erstellen, um ein normales Verhalten zu haben. Dies wird durch diese post und diese post inspiriert.

#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 
+0

+1 yageek, ich hatte mit demselben Problem zu kämpfen, dh mit Core Text konnte ich Text von einigen Schriftarten zeichnen, aber mit nicht allen und schließlich hat Ihre Lösung für mich perfekt funktioniert! Vielen Dank viel für das Teilen Ihrer Antwort yageek. –