2013-02-23 9 views
6

Temel metni kullanarak çizmeye çalıştığım şu kodu kullanıyorum ve bu yüzden metni UILabel'in yaptığı gibi kırpamıyorum. Diğer bir deyişle, elips ('...') kendimi bulmalıyım.NSString'e elips ekleme

CGSize commentSize = [[self.sizeDictionary_ valueForKey:commentSizeKey] CGSizeValue]; 
     CGSize actualSize = [[self.sizeDictionary_ valueForKey:actualCommentSizeKey] CGSizeValue]; 

NSString *actualComment = self.highlightItem_.comment; 
     if (actualSize.height > commentSize.height){ 
      actualComment = [self.highlightItem_.comment stringByReplacingCharactersInRange:NSMakeRange(68, 3) withString:@"..."]; 
     } 

CGSize'ye dayanan '...' aralığını bulmakta zorlanıyorum. Bunu anlamanın en iyi yolu ne olurdu? İşte

bunu çiziyorum nasıl:

CFStringRef string = CFBridgingRetain(actualComment); 
     CFMutableAttributedStringRef comment = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); 
     CFAttributedStringReplaceString (comment ,CFRangeMake(0, 0), string); 

     CGColorRef blue = CGColorRetain([UIColor colorWithRed:131/255.f green:204/255.f blue:253/255.f alpha:1.0].CGColor); 
     CGColorRef gray = CGColorRetain([UIColor colorWithWhite:165/255.f alpha:1.0].CGColor); 

     CFAttributedStringSetAttribute(comment, CFRangeMake(0, [name length]),kCTForegroundColorAttributeName, blue); 
     CFAttributedStringSetAttribute(comment, CFRangeMake([name length], [self.highlightItem_.comment length] - [name length]),kCTForegroundColorAttributeName, gray); 

     CGColorRelease (blue); 
     CGColorRelease (gray); 

     CTFontRef nameFont = CTFontCreateWithName(CFBridgingRetain(kProximaNovaBold), 13.0f, nil); 
     CFAttributedStringSetAttribute(comment,CFRangeMake(0, [name length]),kCTFontAttributeName,nameFont); 

     CTFontRef commentFont = CTFontCreateWithName(CFBridgingRetain(kProximaNovaRegular), 13.0f, nil); 
     CFAttributedStringSetAttribute(comment, CFRangeMake([name length], [self.highlightItem_.comment length] - [name length]),kCTFontAttributeName,commentFont); 

     CGFloat commentYOffset = floorf((self.commentHeight_ - commentSize.height)/2); 

     CGContextSaveGState(context); 
     CGRect captionFrame = CGRectMake(0, 0, rect.size.width - 80, commentSize.height); 
     CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(comment); 
     CGMutablePathRef captionFramePath = CGPathCreateMutable(); 
     CGPathAddRect(captionFramePath, NULL, captionFrame); 

     CTFrameRef mainCaptionFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), captionFramePath, NULL); 

     CGContextRef context = UIGraphicsGetCurrentContext(); 
     CGContextSetTextMatrix(context, CGAffineTransformIdentity); 
     CGContextTranslateCTM(context, self.buttonSize_ + 25, self.imageHeight_ + self.commentHeight_ + 6 - commentYOffset); 
     CGContextScaleCTM(context, 1.0, -1.0); 

     CTFrameDraw(mainCaptionFrame, context); 
     CGContextRestoreGState(context); 
+0

için yaklaşık sen 'NSString drawAtPoint kullanabilir miyim: forWidth: withFont: lineBreakMode: '(veya benzer) yöntemi' NSLineBreakByTruncatingTail 'satır sonu modu olarak geçiyor? – rmaddy

+0

@rmaddy Metni nasıl çizdiğimi göstermek için yukarıdaki yazıyı düzenledim. Aslında drawAtPoint – adit

+0

kullanmıyorum Şu anda bulamadığım halde otomatik olarak elips yapmak için bir tesis var eminim. (Belki de NSFont'u düşünüyordum, ama orada göremiyorum.) –

cevap

5

DÜZENLEME

(Benim buradaki asıl yanıtın yararlı değildi; herkes tarihsel için görmek istiyorsa o birden fazla satır ele vermedi. o çözer daha karışıklığa neden beri ilgi, düzenleme tarihinin bakın. sildikten. anki cevap doğru koddur.)

ne yapmanız gereken EXCEP tüm hatları CTFramesetter çalışmaları let olduğunu Sonuncusu. Sonra gerekirse sonuncuyu el ile kesebilirsiniz.

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSetTextMatrix(context, CGAffineTransformIdentity); 

    CGRect pathRect = CGRectMake(50, 200, 200, 40); 
    CGPathRef path = CGPathCreateWithRect(pathRect, NULL); 

    CFAttributedStringRef attrString = (__bridge CFTypeRef)[self attributedString]; 

    // Create the framesetter using the attributed string 
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString); 

    // Create a single frame using the entire string (CFRange(0,0)) 
    // that fits inside of path. 
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); 

    // Draw the lines except the last one 
    CFArrayRef lines = CTFrameGetLines(frame); 
    CFIndex lineCount = CFArrayGetCount(lines); 
    CGPoint origins[lineCount]; // I'm assuming that a stack variable is safe here. 
           // This would be bad if there were thousdands of lines, but that's unlikely. 
    CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins); 
    for (CFIndex i = 0; i < lineCount - 1; ++i) { 
    CGContextSetTextPosition(context, pathRect.origin.x + origins[i].x, pathRect.origin.y + origins[i].y); 
    CTLineDraw(CFArrayGetValueAtIndex(lines, i), context); 
    } 

    /// 
    /// HERE'S THE INTERESTING PART 
    /// 
    // Make a new last line that includes the rest of the string. 
    // The last line is already truncated (just with no truncation mark), so we can't truncate it again 
    CTLineRef lastLine = CFArrayGetValueAtIndex(lines, lineCount - 1); 
    CFIndex lastLocation = CTLineGetStringRange(lastLine).location; 
    CFRange restRange = CFRangeMake(lastLocation, CFAttributedStringGetLength(attrString) - lastLocation); 
    CFAttributedStringRef restOfString = CFAttributedStringCreateWithSubstring(NULL, attrString, restRange); 
    CTLineRef restLine = CTLineCreateWithAttributedString(restOfString); 


    // We need to provide the truncation mark. This is an ellipsis (Cmd-semicolon). 
    // You could also use "\u2026". Don't use dot-dot-dot. It'll work, it's just not correct. 
    // Obviously you could cache this… 
    CTLineRef ellipsis = CTLineCreateWithAttributedString((__bridge CFTypeRef) 
                 [[NSAttributedString alloc] initWithString:@"…"]); 

    // OK, now let's truncate it and draw it. I'm being a little sloppy here. If ellipsis could possibly 
    // be wider than the path width, then this will fail and truncateLine will be NULL and we'll crash. 
    // Don't do that. 
    CTLineRef truncatedLine = CTLineCreateTruncatedLine(restLine, 
                 CGRectGetWidth(pathRect), 
                 kCTLineTruncationEnd, 
                 ellipsis); 
    CGContextSetTextPosition(context, pathRect.origin.x + origins[lineCount - 1].x, pathRect.origin.y + origins[lineCount - 1].y); 
    CTLineDraw(truncatedLine, context); 

    CFRelease(truncatedLine); 
    CFRelease(ellipsis); 
    CFRelease(restLine); 
    CFRelease(restOfString); 
    CFRelease(frame); 
    CFRelease(framesetter); 
    CGPathRelease(path); 
} 
+0

Bu örnekte hiç NSLineBreakMode göremiyorum – adit

+0

Aslında CFRelease'i sonda arıyorum, şimdi burada gösteriyorum – adit

+0

Evet, ancak 'kCTParagraphStyleSpecifierAlignment' örnekte ve satır sonu temelde aynıdır. –

1

Nasıl böyle bir şey ...

- (NSString *)truncate:(NSString *)string toWidth:(CGFloat)width withFont:(UIFont *)font { 

    CGSize size = [string sizeWithFont:font]; 
    if (size.width <= width) return string; 

    NSString *truncatedString = [string copy]; 
    NSString *ellipticalString = [truncatedString stringByAppendingString:@"..."]; 
    size = [ellipticalString sizeWithFont:font]; 

    while (size.width > width && truncatedString.length) { 
     truncatedString = [truncatedString substringToIndex:(truncatedString.length-1)]; 
     ellipticalString = [truncatedString stringByAppendingString:@"..."]; 
     size = [ellipticalString sizeWithFont:font]; 
    } 
    return ellipticalString; 
} 
0

en kolay ve en basit yolu,

NSString *theText = @"bla blah bla bhla bla bla"; 
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 
[style setLineBreakMode:NSLineBreakByTruncatingTail]; 
[theText drawInRect:dirtyRect withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:style, NSParagraphStyleAttributeName,nil]]; 

more