2013-02-23 44 views
6

Tôi có đoạn mã sau, mà tôi đang cố gắng vẽ bằng văn bản lõi và đó là lý do tại sao tôi không thể cắt đoạn văn bản giống như những gì UILabel làm. nói cách khác tôi phải tìm ra dấu chấm lửng ('...') của tôi.thêm dấu chấm lửng vào NSString

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:@"..."]; 
     } 

Tôi đang gặp khó khăn khi tìm phạm vi '...' dựa trên CGSize. Điều gì sẽ là cách tốt nhất để tìm ra điều này?

Đây là cách tôi đang vẽ nó:

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

Bạn có thể dùng lệnh 'NSString drawAtPoint: forWidth: phương thức withFont: lineBreakMode: '(hoặc tương tự) truyền' NSLineBreakByTruncatingTail' làm chế độ ngắt dòng? – rmaddy

+0

@rmaddy Tôi đã chỉnh sửa bài đăng ở trên để cho biết cách tôi vẽ văn bản. Tôi thực sự không sử dụng drawAtPoint – adit

+0

Tôi khá chắc rằng có một cơ sở để làm hình elip tự động, mặc dù tôi không thể tìm thấy nó ngay bây giờ. (Nghĩ rằng có lẽ NSFont, nhưng tôi không thấy nó ở đó.) –

Trả lời

5

EDIT

(câu trả lời ban đầu của tôi ở đây là không hữu ích, nó không xử lý nhiều dòng Nếu bất cứ ai muốn nhìn thấy nó cho lịch sử. quan tâm, xem trong lịch sử chỉnh sửa. Tôi đã xóa nó vì nó gây ra nhiều nhầm lẫn hơn giải quyết. Câu trả lời hiện tại là mã chính xác.)

Những gì bạn cần làm là để CTFramesetter làm việc ra tất cả các dòng excep t người cuối cùng. Sau đó, bạn có thể cắt ngắn cuối cùng bằng tay nếu cần thiết.

- (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

Tôi không thấy bất kỳ NSLineBreakMode nào trong ví dụ – adit

+0

Tôi thực sự gọi CFRelease ở cuối, tôi chỉ hiển thị ở đây – adit

+0

Có, nhưng 'kCTParagraphStyleSpecifierAlignment' là trong ví dụ và ngắt dòng về cơ bản là giống nhau. –

1

Làm thế nào về một cái gì đó như thế này ...

- (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

Cách dễ nhất và đơn giản nhất,

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

cho more

Các vấn đề liên quan