【问题标题】:How to get the size of a NSString如何获取 NSString 的大小
【发布时间】:2011-02-09 18:37:09
【问题描述】:

“快速”:如何获取 NSString 的大小(宽度)?

我正在尝试查看字符串的字符串宽度是否大于给定的屏幕宽度,在这种情况下我必须“裁剪”它并附加“...”,得到UILabel 的通常行为。 string.length 无法解决问题,因为 AAAAAAA 和 iiiiii 的长度相同但大小不同(例如)。

我有点卡住了。

非常感谢。

【问题讨论】:

  • 虽然不是一个完整的答案...我认为大多数 iOS 和 MacOS 文本字段渲染器都有这种“截断”模式,在文本被截断的地方添加省略号 (...) --- 自动.整个需要自己做这件事然后就消失了。

标签: iphone objective-c xcode nsstring width


【解决方案1】:

不管它的价值——我认为 OP 采取了错误的方式到达那里......如果宽度的测量只用于找到应该剪切文本的位置,然后是省略号 --- 那么 OP应该知道这个功能在 Cocoa 中的所有文本视图中都实现了...

注意这个枚举:

typedef NS_ENUM(NSUInteger, NSLineBreakMode) {
    NSLineBreakByWordWrapping = 0,         // Wrap at word boundaries, default
    NSLineBreakByCharWrapping,        // Wrap at character boundaries
    NSLineBreakByClipping,        // Simply clip
    NSLineBreakByTruncatingHead,    // Truncate at head of line: "...wxyz"
    NSLineBreakByTruncatingTail,    // Truncate at tail of line: "abcd..."
    NSLineBreakByTruncatingMiddle    // Truncate middle of line:  "ab...yz"
} API_AVAILABLE(macos(10.0), ios(6.0), watchos(2.0), tvos(9.0));

通过将您的文本字段或文本视图的换行模式设置为NSLineBreakByTruncatingTail,您将实现您想要的,并且可能以更高的质量实现,而无需自己实现。

【讨论】:

    【解决方案2】:

    使用下面的方法。

    Objective-C

    - (CGSize)findHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font {
        CGSize size = CGSizeZero;
        if (text) {
            CGRect frame = [text boundingRectWithSize:CGSizeMake(widthValue, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName:font } context:nil];
            size = CGSizeMake(frame.size.width, frame.size.height + 1);
        }
        return size;
    }
    

    Swift 3.0

    func findHeight(forText text: String, havingWidth widthValue: CGFloat, andFont font: UIFont) -> CGSize {
        var size = CGSizeZero
        if text {
            var frame = text.boundingRect(withSize: CGSize(width: widthValue, height: CGFLOAT_MAX), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
            size = CGSize(width: frame.size.width, height: frame.size.height + 1)
        }
        return size
    }
    

    【讨论】:

    • 为什么高度 + 1?
    • size = CGSize(width: ceilf(frame.width), height: ceilf(frame.height)) 更好。
    • 问题是问如何获取字符串的宽度。如果您已经知道字符串的宽度,这个答案是如何获取字符串的高度......很好的信息,但不是问题的答案。我认为做出这个答案的更好方法是提出正确的问题,然后自己回答,然后对该问题提出可能的评论,将您指向相关问题。
    【解决方案3】:
    sizeWithFont:constrainedToSize:lineBreakMode 
    

    现在已弃用。使用下面的代码sn-p,

    UIFont *font=[UIFont fontWithName:@"Arial" size:16.f];
    
    NSString *name = @"APPLE";
    
    CGSize size = [name sizeWithAttributes:@{NSFontAttributeName:font}];
    

    【讨论】:

      【解决方案4】:

      这是一种不同的方法。找出文本的最小大小,使其不会换行超过一行。如果它超过了一行,你可以用高度找出来。

      您可以使用此代码:

      CGSize maximumSize = CGSizeMake(300, 9999);
      NSString *myString = @"This is a long string which wraps";
      UIFont *myFont = [UIFont fontWithName:@"Helvetica" size:14];
      CGSize myStringSize = [myString sizeWithFont:myFont 
                                 constrainedToSize:maximumSize 
                                     lineBreakMode:self.myLabel.lineBreakMode];
      

      300 是屏幕的宽度,留有一点边距。如果您不使用 IB,您应该将自己的值替换为字体和大小,以及 lineBreakMode

      现在myStringSize 将包含一个height,您可以检查它的高度,您知道它只有 1 行高(使用相同的字体和大小)。如果它更大,则需要剪切文本。请注意,您应该在再次检查之前将 ... 添加到字符串中(添加 ... 可能会再次将其推过限制)。

      将此代码放入循环中以剪切文本,然后再次检查正确的高度。

      【讨论】:

      • 非常感谢!您的答案是正确的,在再次检查大小之前附加“...”的技巧是明智的。
      • 对于 iOS 7,您应该查看 this answer
      • 这不起作用。 NSString.StringSize(UIFont font, nfloat forWidth, UILineBreakMode breakMode) 是一个有缺陷的方法,它总是返回单行的高度,即使使用 UILineBreakMode.WordWrap 并传入一个字符串,该字符串应该为给定的宽度换行到多行。有人知道为什么吗?或者谁能​​提供更好的解决方案?
      【解决方案5】:

      您需要使用 Core Graphics 来测量以您指定的字体和大小呈现的字符串。请参阅Measuring the pixel width of a string 的答案以进行演练。

      【讨论】:

        猜你喜欢
        • 2013-04-04
        • 1970-01-01
        • 2013-07-05
        • 2014-10-18
        • 2011-07-05
        • 2011-03-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多