How to tell when a UILabel will be truncated an/or its line break position will change

后端 未结 5 1303
栀梦
栀梦 2021-01-13 01:38

I have a multi-line UILabel (numberOfLines = 0). It\'s width can change at runtime, and sometimes this leads to truncation and/or re-wrapping. Some

相关标签:
5条回答
  • 2021-01-13 02:18

    Use this method to find lable truncated in iOS 7.

    - (BOOL)isTruncated:(UILabel *)label{
            CGSize sizeOfText = [label.text boundingRectWithSize: CGSizeMake(label.bounds.size.width, CGFLOAT_MAX)
                                                         options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                                      attributes: [NSDictionary dictionaryWithObject:label.font forKey:NSFontAttributeName] context: nil].size;
    
            if (self.frame.size.height < ceilf(sizeOfText.height)) {
                return YES;
            }
            return NO;
        }
    
    0 讨论(0)
  • 2021-01-13 02:29

    The answer above is using a depreciated method, so i thought the following code could be useful:

    - (BOOL)isLabelTruncated:(UILabel *)label
    {
        BOOL isTruncated = NO;
    
        CGRect labelSize = [label.text boundingRectWithSize:CGSizeFromString(label.text) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : label.font} context:nil];
    
        if (labelSize.size.width / labelSize.size.height > label.numberOfLines) {
    
            isTruncated = YES;
        }
    
        return isTruncated;
    }
    
    0 讨论(0)
  • 2021-01-13 02:33

    Swift 3 solution

    You can count the number of lines after assigning the string and compare to the max number of lines of the label.

    import Foundation
    import UIKit
    
    extension UILabel {
    
        func countLabelLines() -> Int {
            // Call self.layoutIfNeeded() if your view is uses auto layout
            let myText = self.text! as NSString
            let attributes = [NSFontAttributeName : self.font]
    
            let labelSize = myText.boundingRect(with: CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: attributes, context: nil)
            return Int(ceil(CGFloat(labelSize.height) / self.font.lineHeight))
        }
    
        func isTruncated() -> Bool {
    
            if (self.countLabelLines() > self.numberOfLines) {
                return true
            }
            return false
        }
    }
    
    0 讨论(0)
  • 2021-01-13 02:35

    For versions higher than iOS 7, you can check the following solutions:

    1. https://stackoverflow.com/a/30813691/2123122
    2. https://stackoverflow.com/a/32094824/2123122
    0 讨论(0)
  • 2021-01-13 02:37

    You could know the size of label that is needed to display a particular NSString instance. For example, you could use that one:

    - (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode

    Returns the size of the string if it were rendered with the specified constraints.

    So what you want is to get CGSize for a particular string and check if it is not larger then UILabel size:

        UILabel *label;
        CGSize sizeNeeded = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(label.bounds.size.width, MAXFLOAT)];
        if (sizeNeeded.height > label.bounds.size.height)
        {
            NSLog(@"String is truncated");
        }
    

    More useful NSString methods you could find here: NSString UIKit Additions Reference

    Ok, another way of doing what you want:

    1) Create 2 UILabel with the same properties but second one (label2) will be with another one width.

    2) Set alpha property of label2 to 0.0 in non-edit mode.

    3) When edit mode begins make such animation:

    // label1.alpha == 1.0, label2.alpha == 0.0 
    {[UIView animateWithDuration:0.5 animations:^{
        label1.alpha = 0.0;
        label2.alpha = 1.0;
    }];
    

    4) When edit mode ends:

    {[UIView animateWithDuration:0.5 animations:^{
        label1.alpha = 1.0;
        label2.alpha = 0.0;
    }];
    

    That will give you the same result as in Mail.app

    0 讨论(0)
提交回复
热议问题