如何判断一个UILabel将被截断和/或其换行符位置将会改变

我有一个多行UILabelnumberOfLines = 0)。 它的宽度可以在运行时改变,有时会导致截断和/或重新包装。 一些例子说明了这一点:

示例1:宽度的减小导致不同的折线点

在这里输入图像说明在这里输入图像说明

例2:宽度的减less导致截断

在这里输入图像说明在这里输入图像说明

示例3:宽度的减小导致截断和不同的换行符位置

在这里输入图像说明在这里输入图像说明

示例4:宽度的减小对截断或换行位置没有任何影响

在这里输入图像说明在这里输入图像说明

由于这种格式的变化可能会相当刺耳,我打算在一些animation背后隐藏它(可能是淡入/淡出)。 但是,第一个障碍是确定何时需要这样做。 我不想在标签重新resize时应用animation – 只有当它会导致截断或换行符位置发生变化时。

我该如何testing呢? 例如,testing应返回“是”,例如1,2和3,否则返回例如4。

注意:resize不会改变我的例子中的行数。

注2:如果有人有更好的标签相关的文字格式我很想知道他们 – 随时编辑。

注3:如果你有兴趣看到这种行为完成,请尝试苹果的iPhone上的mail.app。 查看收件箱时,轻扫一封电子邮件并观看摘要行淡入/淡出,因为它重新包装和/或截断(但不是当不需要时)。

您可以知道显示特定NSString实例所需的标签大小。 例如,你可以使用那个:

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

如果使用指定的约束呈现string,则返回string的大小。

所以你想要的是为特定的string获取CGSize ,并检查它是否不大于UILabel大小:

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

更有用的NSString方法,你可以在这里find: NSString UIKit Additions Reference

好吧,做你想做的另一种方式:

1)创build2个具有相同属性的UILabel ,但是第二个( label2 )将具有另一个width

2)在非编辑模式下将label2 alpha属性设置为0.0

3)编辑模式开始时,进行这样的animation:

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

4)编辑模式结束时:

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

这会给你在Mail.app相同的结果

Swift 3解决scheme

您可以在分配string之后计算行数,并与标签的最大行数进行比较。

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

上面的答案是使用折旧方法,所以我认为下面的代码可能是有用的:

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

使用这个方法来查找标签在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; } 

对于高于iOS 7的版本,您可以检查以下解决scheme:

  1. https://stackoverflow.com/a/30813691/2123122
  2. https://stackoverflow.com/a/32094824/2123122