6

I have a UILabel in my iPhone project that has a fixed width and height but it's content can vary depending what the user is looking at. Sometimes the text is to big for the UILabel and that is when the string: '...', gets added to the end of the line. I wonder if I could change this string to something else, for instance: '(more)'.

Thanks!

Mattias Farnemyhr
  • 4,148
  • 3
  • 28
  • 49
  • Have you considered setting the label's `adjustsFontSizeToFitWidth` property to YES in order to have the label adjust font size automatically? – kevboh May 01 '12 at 00:40
  • I think @thematerik is talking about behavior when it hits the min font size then truncates replacing with ellipses. This is an interesting question. – danh May 01 '12 at 00:43

3 Answers3

2

Unfortunately, it appears that such an option is not included on iOS, as per this similar question: How to change truncate characters in UILabel?

However, as the answers in the aforementioned question state, this can be easily done yourself. All you really need to do is find where the string gets truncated and subtract the amount needed for your chosen ending character(s). Then put the remainder in a separate string.

For this method, this answer would also be useful:

As Javanator said you would have to do your own truncation. You shuld use the sizeWithFont:forWidth:lineBreakMode: message on the UIKit additions to NSString class to get the width of a string with a certain font. This will handle all types of fonts.

Community
  • 1
  • 1
Zigsaz
  • 435
  • 3
  • 15
1

I thought this was an interesting question, so built and barely tested this...

- (void)setText:(UILabel *)label withText:(NSString *)text andTruncationSuffix:(NSString *)truncationSuffix {

    // just set the text if it fits using the minimum font
    //
    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:label.minimumFontSize]];
    if (size.width <= label.bounds.size.width) {
        label.text = text;
        return;
    }

    // build a truncated version of the text (using the custom truncation text)
    // and shrink the truncated text until it fits
    NSInteger lastIndex = text.length;
    CGFloat width = MAXFLOAT;

    NSString *subtext, *ellipticalText;

    while (lastIndex > 0 && width > label.bounds.size.width)  {
        subtext = [text substringToIndex:lastIndex];
        ellipticalText = [subtext stringByAppendingString:truncationSuffix];
        width = [ellipticalText sizeWithFont:[UIFont systemFontOfSize:label.minimumFontSize]].width;
        lastIndex--;
    }
    label.text = ellipticalText;
}

Call it like this:

[self setText:self.label withText:@"Now is the time for all good men to come to the aid of their country" andTruncationSuffix:@" more"];

If this works for you, you could consider adding a subclass of UILabel, using this to override the setText: method, and adding a property called truncatedSuffix.

danh
  • 62,181
  • 10
  • 95
  • 136
  • At the time text was set, label's width may not be determined yet especially if you are using Autolayout. – Ozgur Vatansever Dec 11 '15 at 19:17
  • @ozgur - yeah, this post is pretty outdated now, given auto layout and all the new typography stuff. even `sizeWithFont` is deprecated now. maybe i'll rewrite it at some point soon. – danh Dec 11 '15 at 21:58
1

If you are using iOS version > 8.0, you can use ResponsiveLabel. Here you can provide customised truncation token as well as define actions to make it tappable.

NSString *expansionToken = @"Read More ...";
NSString *str = @"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
NSMutableAttributedString *attribString = [[NSMutableAttributedString alloc]initWithString:kExpansionToken attributes:@{NSForegroundColorAttributeName:[UIColor blueColor],NSFontAttributeName:self.customLabel.font}];
[self.customLabel setAttributedTruncationToken:attribString withAction:^(NSString *tappedString) {
 NSLog(@"Tap on truncation text");
}];
[self.customLabel setText:str withTruncation:YES];
hsusmita
  • 282
  • 3
  • 16