2013-09-29 7 views
5

Mam niestandardowego UIView, który jest rysunek NSString poprzez CoreText:NSString boundingRectWithSize wysokość skrócania z Coresetext 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); 
} 

innej klasy Mam następnie próbuje użyć boundingRectWithSize obliczyć, jak długo widok będzie wyświetlany tekst (I potem ustawić a UIScrollView, aby dopasować to):

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

Metoda getAttributedString jest powyżej. Problem polega na tym, że tekstView jest nieco za krótki i dlatego odcina ostatnią linię tekstu. Czy ktoś może sugerować, co jest nie tak?

Co więcej, na marginesie, dlaczego rozmiar w borderingRectWithSize musi być 315 (czyli nieco krótszy niż szerokość ekranu) zamiast 320, aby zadziałał? W 320 tekstViewView jest nieco zbyt szeroki dla ekranu.

Edycja - wydaje się, że dzieje się tak tylko w przypadku niektórych czcionek - np. Verdana działa poprawnie. Czy ktoś bardziej kompetentny wie, czy to ma coś wspólnego z glifami?

Dzięki!

Odpowiedz

0

Ah - wydaje CoreText tekst obowiązuje inaczej metody boundingBox: How does line spacing work in Core Text? (and why is it different from NSLayoutManager?)

+0

W jaki sposób różne odstępy między wierszami pasują do kodu, aby uzyskać odpowiedni rozmiar? Zmagałem się z tą kwestią rozmiarów (używając tableview) również w ciągu ostatnich kilku miesięcy i to jest pierwszy trop, jaki widziałem. – guthook

+1

Spróbuj zmienić typ czcionki - wydaje się, że dzieje się tak tylko w przypadku niektórych czcionek. – GuybrushThreepwood

+0

Fajnie, dziękuję za informację. Spojrzałem trochę dalej i znalazłem to, co może pomóc: http://stackoverflow.com/a/18818036/1275947 – guthook

3

W projekcie MMProgressHud, różne rozmiary poszczególnych elementów są obliczane za pomocą boundingRectWithSize:options:context: metody i miałem jakiś problem przy użyciu czcionki HelveticaNeue-Light ale nie jeden przy użyciu czcionki Verdana.

Stworzyłem nową kategorię na NSString, aby moja własna metoda pomiaru używała Core-Text do regularnego zachowania. Inspiracją tego jest ta post i ta post.

#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, zmagałem się z tym samym problemem tj. używając Core Text udało mi się narysować tekst niektórych czcionek, ale nie wszystko i wreszcie Twoje rozwiązanie zadziałało idealnie! Dziękuję za dzielenie się swoją odpowiedzią yageek. –

Powiązane problemy