2010-06-19 149 views
69

我有一個UILabel,根據我的應用程序是否在iPhone或iPad上以縱向或橫向模式運行,可能會有不同的長度。當文本太長而無法在一行顯示時,它會截斷,我希望用戶能夠按下它並獲得全文的彈出窗口。如何檢查UILabel是否被截斷?

如何檢查UILabel是否截斷了文本?它甚至有可能嗎?現在我只是根據我在哪種模式下檢查不同的長度,但它不能很好地工作。

+1

,看一下該解決方案基於線指望我張貼[這裏](http://stackoverflow.com/questions/3077109/how-to-check-if-uilabel-is-truncated/43002072# 43002072) – Claus 2017-03-24 14:29:28

回答

83

可以計算width of the string,看看寬度大於label.bounds.size.width

NSString UIKit Additions具有用於與特定字體計算所述字符串的大小的幾種方法。但是,如果您的標籤具有minimumFontSize,則允許系統將文本縮小到該尺寸。在這種情況下,您可能需要使用sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:

CGSize size = [label.text sizeWithAttributes:@{label.font}]; 
if (size.width > label.bounds.size.width) { 
    ... 
} 
+1

謝謝,這正是我所需要的。唯一的區別是,sizeWithFont:返回一個CGSize。 – Randall 2010-06-23 03:27:56

+0

啊,謝謝你指出,我已經糾正了示例代碼。 – progrmr 2010-06-23 03:53:28

+5

它只適用於label.numberofline == 0,不是嗎? – Martin 2012-11-07 15:32:43

9

你可以做一個分類均具有的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; 
} 
+3

from doc:'textRectForBounds:limitedToNumberOfLines:''你不應該直接調用這個方法「... – Martin 2012-11-07 15:25:08

+0

@Martin謝謝,我明白了,這裏的工具是有限的,但是當你在設置邊界和文本後調用這個方法時,它會工作得很好 – DongXu 2012-11-09 05:56:45

+0

爲什麼在設置restrictToNumberOfLines時會+1? – Ash 2015-12-17 15:12:57

19

編輯:我剛剛看到我的答案是upvoted,但代碼片段我放棄已經過時了。
我們做到這一點,最好的方法是(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"); 
} 

注意計算的大小是不是整數值。因此,如果您執行諸如int height = rect.size.height之類的操作,將會失去一些浮點精度,並可能導致錯誤結果。

老答案(不推薦):

如果您的標籤是多,你可以使用此代碼:因爲所有上述使用的答案折舊方法

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"); 
} 
0

,我想這可能是有用的:

- (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

您將寬度除以高度,如果它大於行數(可能非常好),則表示標籤被截斷。這是行不通的。 – 2015-03-23 17:14:40

+0

@CanLeloğlu請測試它。這是一個工作的例子。 – Raz 2015-03-24 14:37:24

+2

如果numberOfLines等於零怎麼辦? – 2015-03-27 17:40:23

8

使用此類別查找iOS 7及更高版本上的標籤是否被截斷。

// UILabel+Truncation.h 
@interface UILabel (Truncation) 

@property (nonatomic, readonly) BOOL isTruncated; 

@end 


// UILabel+Truncation.m 
@implementation UILabel (Truncation) 

- (BOOL)isTruncated 
{ 
    CGSize sizeOfText = 
     [self.text boundingRectWithSize:CGSizeMake(self.bounds.size.width, CGFLOAT_MAX) 
           options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) 
          attributes:@{ NSFontAttributeName : label.font } 
           context: nil].size; 

    if (self.frame.size.height < ceilf(sizeOfText.height)) 
    { 
     return YES; 
    } 
    return NO; 
} 

@end 
1

要添加到什麼@iDev做,我修改了self.frame.size.height使用label.frame.size.height,也沒有使用NSStringDrawingUsesLineFontLeading。經過這些修改後,我完成了截斷時間的完美計算(至少在我的情況下)。

- (BOOL)isTruncated:(UILabel *)label { 
    CGSize sizeOfText = [label.text boundingRectWithSize: CGSizeMake(label.bounds.size.width, CGFLOAT_MAX) 
               options: (NSStringDrawingUsesLineFragmentOrigin) 
               attributes: [NSDictionary dictionaryWithObject:label.font forKey:NSFontAttributeName] context: nil].size; 

    if (label.frame.size.height < ceilf(sizeOfText.height)) { 
     return YES; 
    } 
    return NO; 
} 
7

爲了增加iDev的回答,你應該使用intrinsicContentSize而不是frame,使之適用於自動佈局

- (BOOL)isTruncated:(UILabel *)label{ 
     CGSize sizeOfText = [label.text boundingRectWithSize: CGSizeMake(label.intrinsicContentSize.width, CGFLOAT_MAX) 
                options: (NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) 
                attributes: [NSDictionary dictionaryWithObject:label.font forKey:NSFontAttributeName] context: nil].size; 

     if (self.intrinsicContentSize.height < ceilf(sizeOfText.height)) { 
     return YES; 
    } 
    return NO; 
} 
+0

謝謝!使用intrinsicContentSize而不是frame是UILabel height實際上足以適應文本的問題的解決方案,但它的行數有限,因此仍然被截斷。 – 2015-06-25 01:16:15

+0

由於某些原因,即使文本不符合標籤 – 2017-03-12 22:29:05

2

這適用於iOS的8:

CGSize size = [label.text boundingRectWithSize:CGSizeMake(label.bounds.size.width, NSIntegerMax) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : label.font} context:nil].size; 

if (size.height > label.frame.size.height) { 
    NSLog(@"truncated"); 
} 
0

要處理iOS 6(是的,我們中的一些人仍然需要),這是對iDev答案的又一次擴展。關鍵是,對於iOS 6,在調用sizeThatFits之前確保你的UILabel的numberOfLines被設置爲0;如果沒有,它會給你一個結果,說「繪製numberOfLines值得高度的點」是繪製標籤文本所必需的。

- (BOOL)isTruncated 
{ 
    CGSize sizeOfText; 

    // iOS 7 & 8 
    if([self.text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) 
    { 
     sizeOfText = [self.text boundingRectWithSize:CGSizeMake(self.bounds.size.width,CGFLOAT_MAX) 
              options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) 
              attributes:@{NSFontAttributeName:self.font} 
              context:nil].size; 
    } 
    // iOS 6 
    else 
    { 
     // For iOS6, set numberOfLines to 0 (i.e. draw label text using as many lines as it takes) 
     // so that siteThatFits works correctly. If we leave it = 1 (for example), it'll come 
     // back telling us that we only need 1 line! 
     NSInteger origNumLines = self.numberOfLines; 
     self.numberOfLines = 0; 
     sizeOfText = [self sizeThatFits:CGSizeMake(self.bounds.size.width,CGFLOAT_MAX)]; 
     self.numberOfLines = origNumLines; 
    } 

    return ((self.bounds.size.height < sizeOfText.height) ? YES : NO); 
} 
3

我寫了一個使用UILabel截斷的類。適用於iOS 7及更高版本。希望能幫助到你 ! uilabel tail truncation

@implementation UILabel (Truncation) 

- (NSRange)truncatedRange 
{ 
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:[self attributedText]]; 

    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; 
    [textStorage addLayoutManager:layoutManager]; 

    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size]; 
    textContainer.lineFragmentPadding = 0; 
    [layoutManager addTextContainer:textContainer]; 

    NSRange truncatedrange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:0]; 
    return truncatedrange; 
} 

- (BOOL)isTruncated 
{ 
    return [self truncatedRange].location != NSNotFound; 
} 

- (NSString *)truncatedText 
{ 
    NSRange truncatedrange = [self truncatedRange]; 
    if (truncatedrange.location != NSNotFound) 
    { 
     return [self.text substringWithRange:truncatedrange]; 
    } 

    return nil; 
} 

@end 
+0

@ Politank-Z,這也會返回NO。謝謝,我剛剛編輯了答案。 – 2015-06-13 12:09:32

48

夫特(如延伸) - 適用於多行的UILabel:

swift4:(的boundingRectattributes PARAM稍微改變)

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 
    } 

} 
+0

替換CGFloat的(FLT_MAX)的999999.0高度 – ambientlight 2016-03-25 08:28:05

+2

爲SWIFT 3我會用CGFloat.greatestFiniteMagnitude – zero3nna 2016-12-01 15:44:29

+2

不錯的答案,但它能夠更好地改用FUNC的計算性能: VAR isTruncated:布爾{ 如果讓字符串= {self.text 讓size:CGSize =(string as NSString).boundingRect( with:CGSize(width:self.frame.size.width,height:CGFloat.greatestFiniteMagnitude), options:NSStringDrawingOptions.usesLineFragmentOrigin, attributes:[NSFontAttributeName:self。字體], 上下文:無).size return(size.height> self.bounds.size.height) } return false } – Mohammadalijf 2017-05-31 21:13:03

-5

難以輕鬆設置標籤的標題屬性,設置它將在懸停時顯示完整標籤。

您可以計算標籤的長度和div的寬度(轉換爲長度 - jQuery/Javascript - How do I convert a pixel value (20px) to a number value (20))。

設置jquery設置標題,如果長度大於div寬度。

var divlen = parseInt(jQuery("#yourdivid").width,10); 
var lablen =jQuery("#yourlabelid").text().length; 
if(lablen < divlen){ 
jQuery("#yourlabelid").attr("title",jQuery("#yourlabelid").text()); 
} 
+0

這是JavaScript。 – 2016-03-08 01:00:10

-1

斯威夫特3溶液

我認爲最好的辦法是(1)創建具有相同的屬性,你正在檢查截斷標籤,UILabel(2 )致電.sizeToFit(),(3)比較虛標籤的屬性與您的實際標籤。

例如,如果你想檢查已經改變寬度的一個內襯標籤是否截斷或沒有,那麼你可以使用這個擴展:

extension UILabel { 
    func isTruncated() -> Bool { 
     let label = UILabel(frame: CGRect(x: 0, y: 0, width: CGFloat.greatestFiniteMagnitude, height: self.bounds.height)) 
     label.numberOfLines = 1 
     label.font = self.font 
     label.text = self.text 
     label.sizeToFit() 
     if label.frame.width > self.frame.width { 
      return true 
     } else { 
      return false 
     } 
    } 
} 

...但同樣,你可以輕鬆地修改以上代碼來滿足您的需求。所以我們假設您的標籤是多線並且高度不一。然後分機將是這個樣子:

extension UILabel { 
    func isTruncated() -> Bool { 
     let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude)) 
     label.numberOfLines = 0 
     label.font = self.font 
     label.text = self.text 
     label.sizeToFit() 
     if label.frame.height > self.frame.height { 
      return true 
     } else { 
      return false 
     } 
    } 
} 
6

斯威夫特3

您可以分配後弦數行數和比較標籤的行數上限。

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

效果很好,非常感謝 – 2017-11-22 09:48:17