【问题标题】:How to tell when a UILabel will be truncated an/or its line break position will change如何判断 UILabel 何时会被截断和/或其换行位置会改变
【发布时间】:2012-10-08 09:34:56
【问题描述】:

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

示例1:宽度减小导致不同的换行点

示例2:宽度减小导致截断

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

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

由于格式上的这种变化可能非常不和谐,我打算将它隐藏在一些动画后面(可能是淡入/淡出)。但是,第一个障碍是确定何时我需要这样做。我不想在标签重新调整大小时应用动画 - 只有当它会导致截断或换行位置发生变化时。

我该如何测试呢?测试应返回 YES(例如 1、2 和 3),但返回 NO(例如 4)。

注意:在我的示例中,调整大小永远不会改变行数。

注意 2:如果有人有更好的与文本格式相关的标签,我很想知道它们 - 随时编辑。

注意 3:如果您有兴趣看到此行为已完成,请在 iPhone 上尝试 Apple 的 mail.app。查看收件箱时,滑动电子邮件并观察摘要行在重新换行和/或截断时淡入/淡出(但不是在不需要时)。

【问题讨论】:

    标签: objective-c ios cocoa-touch uiview uilabel


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      返回字符串的大小,如果它是使用指定的约束渲染的。

      所以你想要的是获取特定字符串的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 方法可以在这里找到:NSString UIKit Additions Reference

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

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

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

      3) 当编辑模式开始时制作这样的动画:

      // 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 中相同的结果

      【讨论】:

      • 我可以看到这可能有助于确定标签是否会被截断。但我认为它对我没有帮助,例如 4?顺便谢谢你的链接。
      • 什么意思?在任何情况下,它都能彻底解决您的问题。
      • 你说:only when it will cause a change in either truncation or line break positions。我什至给你代码如何检查这个。
      • 对不起,我的意思是示例 1。示例 1 中没有应用截断 - 只是换行符的变化。我将测试 sizeWithFont:... 现在是否能捕捉到这一点。
      • 我测试过,并且怀疑这不起作用,例如一个。文字没有被截断,只有换行改变,所以漏网了。
      【解决方案3】:

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

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

      【讨论】:

      • 标签大小的比例与行数的关系如何?我看不出这是如何工作的(当我测试它时肯定没有)
      【解决方案4】:

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

      【讨论】:

      【解决方案5】:

      对于高于 iOS 7 的版本,您可以查看以下解决方案:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-02
        • 1970-01-01
        • 2011-03-05
        • 1970-01-01
        • 2018-07-05
        • 1970-01-01
        相关资源
        最近更新 更多