Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
543 views
in Technique[技术] by (71.8m points)

objective c - iOS UILabel autoshrink so word doesn't truncate to two lines

I'm trying to have the UILabel shrink so that words don't truncate to the next line. Not just text truncating at the end of the text area.

If I have a box that is 50x100, and I want to put in something like "American" in the box at 25.0pt, I end up getting:

   50px
 -------
|Ameri- |
|can    |
|Beauty | 100px
|       |
 -------

The text shrinking doesn't seem to do anything during this situation, since it still fits in the UILabel frame. It works pretty well when the text is really long like "Willie Wonka's Chocolate Factory", but I don't want word truncation.

This is the ideal output in that scenario:

    50px
 --------
[American|
|Beauty  | 100px
|        |
|        |
|        |
 --------

Any suggestions would be super appreicated!

Edit: SOLUTION

Here is what I ended up doing thanks to the suggestion in the answer below. It works great!

- (CGFloat) calculateFromUILabel:(UILabel *)label
{
    NSString *stringToMeasure = label.text;
    NSLog(@"FontSizeMeasurement.calculateFromUILabel() %@", stringToMeasure);

    NSRange range = NSMakeRange(0, 1);
    NSAttributedString *attributedString = label.attributedText;
    NSDictionary *attributes = [attributedString attributesAtIndex:0 effectiveRange:&range];

    NSMutableCharacterSet *characterSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy];
    [characterSet addCharactersInString:@"-"];
    NSArray *words = [stringToMeasure componentsSeparatedByCharactersInSet:characterSet];

    CGSize maxSize = CGSizeZero;
    NSMutableAttributedString *maxWidthString = nil;
    for(int i = 0; i < words.count; i++) {
        NSString *word = words[i];
        CGSize wordSize = [word sizeWithAttributes:attributes];
        if(wordSize.width > maxSize.width) {
            maxSize = wordSize;
            maxWidthString = [[NSMutableAttributedString alloc] initWithString:word attributes:attributes];
        }
    }

    UIFont *font = [label.font copy];
    while(maxSize.width > self.maxWidth) {
        font = [font fontWithSize:(font.pointSize-0.1)];
        [maxWidthString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, maxWidthString.length)];
        maxSize = [maxWidthString size];
    }

    return font.pointSize;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Just to add Swift 4 version + Add a guard to do it only with adjustsFontSizeToFitWidth true, as user using false won't want to fit by long word I guess.

extension UILabel {
// Adjusts the font size to avoid long word to be wrapped
func fitToAvoidWordWrapping() {
    guard adjustsFontSizeToFitWidth else {
        return // Adjust font only if width fit is needed
    }
    guard let words = text?.components(separatedBy: " ") else {
        return // Get array of words separate by spaces
    }

    // I will need to find the largest word and its width in points
    var largestWord: NSString = ""
    var largestWordWidth: CGFloat = 0

    // Iterate over the words to find the largest one
    for word in words {
        // Get the width of the word given the actual font of the label
        let wordWidth = word.size(withAttributes: [.font: font]).width

        // check if this word is the largest one
        if wordWidth > largestWordWidth {
            largestWordWidth = wordWidth
            largestWord = word as NSString
        }
    }

    // Now that I have the largest word, reduce the label's font size until it fits
    while largestWordWidth > bounds.width && font.pointSize > 1 {
        // Reduce font and update largest word's width
        font = font.withSize(font.pointSize - 1)
        largestWordWidth = largestWord.size(withAttributes: [.font: font]).width
    }
}
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...