How to determine when a UILabel will be truncated or its line break position will change

I have a multi-line UILabel ( numberOfLines = 0). Its width may change at runtime, and sometimes this leads to truncation and / or repacking. Some examples illustrate this best:

Example 1: reducing the width leads to a different point of line break

enter image description hereenter image description here

Example 2: reducing the width leads to truncation

enter image description hereenter image description here

Example 3: decreasing the width results in both truncation and a different line break position

enter image description hereenter image description here

Example 4: decreasing width does not affect truncation or line break position

enter image description hereenter image description here

Since this change in formatting can be quite dramatic, I intend to mask it behind some animation (it may fade in / out). However, the first hurdle is determining when I need to do this. I don’t want to apply animation whenever the label size changes - only when it leads to a change in either truncation or line break position.

How can I check this? The test should return YES, for example, 1, 2, and 3, but NO, for example, 4.

Note. Resizing will never change the number of rows in my example.

Note 2: if someone has the best tags related to text formatting, I would like to know them - feel free to edit.

Note 3: if you are interested in having this behavior, try Apple mail.app on iPhone. While browsing your Inbox, swipe through the email and look at the final fade-in / out line as it wraps and / or truncates again (but not when it's not needed).

+5
ios objective-c cocoa-touch uilabel uiview
Oct 18
source share
5 answers

You can find out the label size needed to display a specific instance of NSString . For example, you can use this:

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

Returns the size of the string if it was rendered with the specified restrictions.

So, you want to get CGSize for a particular string and check if it is larger than 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"); } 

You can find more useful NSString methods here: Help for NCCtring UIKit Add-ons

Ok, another way to do what you want:

1) Create 2 UILabel with the same properties, but the second ( label2 ) will be with a different width .

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

3) When the editing mode starts doing such an animation:

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

4) When the editing mode ends:

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

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

+2
Oct 18 '12 at 2:05
source share
β€” -

Swift 3 Solution

You can count the number of lines after assigning a line and compare with the maximum 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 } } 
+2
Mar 24 '17 at 2:31 on
source share

The answer above uses a method with amortization, so I thought the following code might 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; } 
+1
Apr 23 '14 at 9:02
source share

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; } 
+1
Jul 01 '14 at 10:39
source share

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

  • stack overflow
  • stack overflow
0
Aug 19 '15 at 12:00
source share



All Articles