How to check if UILabel is truncated?
Solution 1
You can calculate the width of the string and see if the width is greater than label.bounds.size.width
NSString UIKit Additions has several methods for computing the size of the string with a specific font. However, if you have a minimumFontSize for your label that allows the system to shrink the text down to that size. You may want to use sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode: in that case.
CGSize size = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];
if (size.width > label.bounds.size.width) {
...
}
Solution 2
Swift (as extension) - works for multi line uilabel:
swift4: (attributes
param of boundingRect
changed slightly)
extension UILabel {
var isTruncated: Bool {
guard let labelText = text else {
return false
}
let labelTextSize = (labelText as NSString).boundingRect(
with: CGSize(width: frame.size.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [.font: font],
context: nil).size
return labelTextSize.height > bounds.size.height
}
}
swift3:
extension UILabel {
var isTruncated: Bool {
guard let labelText = text else {
return false
}
let labelTextSize = (labelText as NSString).boundingRect(
with: CGSize(width: frame.size.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
return labelTextSize.height > bounds.size.height
}
}
swift2:
extension UILabel {
func isTruncated() -> Bool {
if let string = self.text {
let size: CGSize = (string as NSString).boundingRectWithSize(
CGSize(width: self.frame.size.width, height: CGFloat(FLT_MAX)),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: self.font],
context: nil).size
if (size.height > self.bounds.size.height) {
return true
}
}
return false
}
}
Solution 3
EDIT: I just saw my answer was upvoted, but the code snippet I gave is deprecated.
Now the best way to do this is (ARC) :
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.lineBreakMode = mylabel.lineBreakMode;
NSDictionary *attributes = @{NSFontAttributeName : mylabel.font,
NSParagraphStyleAttributeName : paragraph};
CGSize constrainedSize = CGSizeMake(mylabel.bounds.size.width, NSIntegerMax);
CGRect rect = [mylabel.text boundingRectWithSize:constrainedSize
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:attributes context:nil];
if (rect.size.height > mylabel.bounds.size.height) {
NSLog(@"TOO MUCH");
}
Note the calculated size is not integer value. So if you do things like int height = rect.size.height
, you will lose some floating point precision and may have wrong results.
Old answer (deprecated) :
If your label is multiline, you can use this code :
CGSize perfectSize = [mylabel.text sizeWithFont:mylabel.font constrainedToSize:CGSizeMake(mylabel.bounds.size.width, NSIntegerMax) lineBreakMode:mylabel.lineBreakMode];
if (perfectSize.height > mylabel.bounds.size.height) {
NSLog(@"TOO MUCH");
}
Solution 4
Swift 3
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 {
guard numberOfLines > 0 else { return false }
return countLabelLines() > numberOfLines
}
}
Solution 5
you can make a category with UILabel
- (BOOL)isTextTruncated
{
CGRect testBounds = self.bounds;
testBounds.size.height = NSIntegerMax;
CGRect limitActual = [self textRectForBounds:[self bounds] limitedToNumberOfLines:self.numberOfLines];
CGRect limitTest = [self textRectForBounds:testBounds limitedToNumberOfLines:self.numberOfLines + 1];
return limitTest.size.height>limitActual.size.height;
}
Randall
Updated on October 10, 2021Comments
-
Randall over 2 years
I have a
UILabel
that can be varying lengths depending on whether or not my app is running in portrait or landscape mode on an iPhone or iPad. When the text is too long to show on one line and it truncates I want the user to be able to press it and get a popup of the full text.How can I check to see if the
UILabel
is truncating the text? Is it even possible? Right now I'm just checking for different lengths based on what mode I'm in but it does not work super well. -
Randall almost 14 yearsThanks, this is exactly what I needed. The only difference was, sizeWithFont: returns a CGSize.
-
progrmr almost 14 yearsAh, thanks for pointing that out, I've corrected the sample code.
-
Martin over 11 yearsfrom the doc :
textRectForBounds:limitedToNumberOfLines:
"You should not call this method directly"... -
DongXu over 11 years@Martin thank you,I see that,the implement here is limited.but when you call this method after setting bounds and text, it will work well
-
Amelia777 almost 10 yearssizeWithFont is deprecated use: [label.text sizeWithAttributes:@{NSFontAttributeName : label.font}];
-
Can Leloğlu about 9 yearsYou are dividing width by height and if it is bigger than number of line (which might very well be 0) you are saying label is truncated. There is no way this works.
-
Raz about 9 years@CanLeloğlu please test it. It is a working example.
-
Can Leloğlu about 9 yearsWhat if the numberOfLines is equal to zero?
-
Anton Matosov almost 9 yearsThanks! Usage of intrinsicContentSize instead of frame was the solution to my problem when UILabel height is actually enough to fit the text, but it has limited number of lines and thus is still truncating.
-
Ash over 8 yearsWhy do you +1 when setting the limitedToNumberOfLines?
-
ambientlight about 8 yearsreplace height of 999999.0 with CGFloat(FLT_MAX)
-
Paul about 8 years@fatuhoku
numberOfLines
returns the maximum number of lines used to display the text as outlined in theUILabel
class reference: developer.apple.com/library/ios/documentation/UIKit/Reference/… -
zero3nna over 7 yearsfor swift 3 i would use CGFloat.greatestFiniteMagnitude
-
Can Poyrazoğlu about 7 yearsFor some reason, this is returning NO even when the text doesn't fit into the label
-
vrwim about 7 years@Ash to check if the label is higher when it is allowed more room for the text.
-
Mohammadalijf almost 7 yearsnice answer but its better to use calculated property instead of func : var isTruncated: Bool { if let string = self.text { let size: CGSize = (string as NSString).boundingRect( with: CGSize(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: self.font], context: nil).size return (size.height > self.bounds.size.height) } return false }
-
Fadi Abuzant almost 6 yearsif label has number of line try multiply width with number of line like this if (size.width > label.bounds.size.width*label.numberOfLines) { ... }
-
Jovan Jovanovski over 5 yearsThanks for this code, it worked for me apart from some border cases when using auto layout. I fixed them by adding:
setNeedsLayout()
layoutIfNeeded()
at the beginning of the method. -
Bibek over 5 yearsevery time it gives NSNotFound only
-
pulse4life over 5 yearsThis didn't work for me because I was using an NSAttributedString. To get it to work, I needed to modify the attributes value to use: attributedText?.attributes(at: 0, effectiveRange: nil)
-
Crt Gregoric over 5 yearsGreat answer, had to change it a bit for my requirements, but worked perfectly. I was also using an attributed string - so for attributes I used: (attributedText?.attributes(at: 0, effectiveRange: nil) ?? [.font: font]), just make sure to check whether the labelText is not empty when using this solution.
-
JimmyLee over 5 yearsThis is the nice answer for swift. Thanks.
-
amodkanthe over 4 yearsthis working fine for me thanks !!are there any updates or modification for this?
-
Elijah over 4 yearsGreat answer. The only issue is attributedText is never nil, even when you don't set it. So, I implemented this as two vars isTextTruncated and isAttributedTextTruncated.
-
Lucas Chwe over 4 years@Harris it says default is nil in the uilabel.h file
-
Elijah over 4 years@LucasChwe I know, but it's not true in practice. You can try it for yourself and see. fyi, forums.developer.apple.com/thread/118581
-
Glenn Posadas almost 4 yearsAxel's answer didn't work for this. This one did. Thanks!
-
Admin over 3 yearsyou may need to call layoutIfNeeded either on the label or within the code of isTruncated depending on when you are checking this
-
Adrian over 2 yearsdoes
intrinsicContentSize.width
work for both text and attributedText?