ios 如何找到 UILabel 的实际行数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28108745/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:28:27  来源:igfitidea点击:

How to find actual number of lines of UILabel?

iosuilabel

提问by nburk

How can I find the actualnumber of lines of a UILabelafter I have initialized it with a textand a font? I have set its numberOfLinesproperty to 0, so it will expand to however many lines are necessary. But then, how can I find out how many lines it finally got after I set its text?

用 a和 a初始化后,如何找到 a 的实际行数?我已将其属性设置为,因此它将扩展为需要多行。但是,在我设置它之后,我怎样才能知道它最终得到了多少行呢?UILabeltextfontnumberOfLines0text

I found similar questions, but none seems to provide a concise answer and it seems to me that it must be really easy to get it without any overhead on juggling around with the boundingRectWithSizeor sizeWithFont,...

我发现了类似的问题,但似乎没有一个提供简洁的答案,在我看来,它必须很容易得到它,而无需处理boundingRectWithSizeor 的任何开销sizeWithFont,...

采纳答案by Paresh Navadiya

Firstly set text in UILabel

首先在 UILabel 中设置文本

First Option :

第一个选项:

Firstly calculate height for text according to font :

首先根据字体计算文本的高度:

NSInteger lineCount = 0;
CGSize labelSize = (CGSize){yourLabel.frame.size.width, MAXFLOAT};
CGRect requiredSize = [self boundingRectWithSize:labelSize  options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: yourLabel.font} context:nil];

Now calculate number of lines :

现在计算行数:

int charSize = lroundf(yourLabel.font.lineHeight);
int rHeight = lroundf(requiredSize.height);
lineCount = rHeight/charSize;
NSLog(@"No of lines: %i",lineCount);

Second Option :

第二个选项:

 NSInteger lineCount = 0;
 CGSize textSize = CGSizeMake(yourLabel.frame.size.width, MAXFLOAT);
 int rHeight = lroundf([yourLabel sizeThatFits:textSize].height);
 int charSize = lroundf(yourLabel.font.lineHeight);
 lineCount = rHeight/charSize;
 NSLog(@"No of lines: %i",lineCount);

回答by Kurt J

None of these worked for me. Below one did,

这些都不适合我。下面一位做到了,

Swift 4.2:

斯威夫特 4.2:

extension UILabel {
    func calculateMaxLines() -> Int {
        let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity))
        let charSize = font.lineHeight
        let text = (self.text ?? "") as NSString
        let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        let linesRoundedUp = Int(ceil(textSize.height/charSize)) 
        return linesRoundedUp
    }    
}

Swift 4/4.1:

斯威夫特 4/4.1:

extension UILabel {

    func calculateMaxLines() -> Int {
        let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity))
        let charSize = font.lineHeight
        let text = (self.text ?? "") as NSString
        let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil)
        let linesRoundedUp = Int(ceil(textSize.height/charSize)) 
        return linesRoundedUp
    }

}

Swift 3:

斯威夫特 3:

extension UILabel {

    func calculateMaxLines() -> Int {
        let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity))
        let charSize = font.lineHeight
        let text = (self.text ?? "") as NSString
        let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
        let linesRoundedUp = Int(ceil(textSize.height/charSize)) 
        return linesRoundedUp
    }

}

回答by ramchandra n

Swift 5 (IOS 12.2)

斯威夫特 5 (IOS 12.2)

Get max number of lines required for a label to render the text without truncation.

获取标签在不截断的情况下呈现文本所需的最大行数。

extension UILabel {
    var maxNumberOfLines: Int {
        let maxSize = CGSize(width: frame.size.width, height: CGFloat(MAXFLOAT))
        let text = (self.text ?? "") as NSString
        let textHeight = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil).height
        let lineHeight = font.lineHeight
        return Int(ceil(textHeight / lineHeight))
    }
}

Get max number of lines can be displayed in a label with constrained bounds. Use this property after assigning text to label.

获取可以在具有约束边界的标签中显示的最大行数。在将文本分配给标签后使用此属性。

extension UILabel {
    var numberOfVisibleLines: Int {
        let maxSize = CGSize(width: frame.size.width, height: CGFloat(MAXFLOAT))
        let textHeight = sizeThatFits(maxSize).height
        let lineHeight = font.lineHeight
        return Int(ceil(textHeight / lineHeight))
    }
}

Usage

用法

print(yourLabel.maxNumberOfLines)
print(yourLabel.numberOfVisibleLines)

回答by danywarner

Here is a swift versionof @Paresh solution:

这是@Paresh 解决方案的快速版本

func lines(label: UILabel) -> Int {
    let textSize = CGSize(width: label.frame.size.width, height: CGFloat(Float.infinity))
    let rHeight = lroundf(Float(label.sizeThatFits(textSize).height))
    let charSize = lroundf(Float(label.font.lineHeight))
    let lineCount = rHeight/charSize
    return lineCount
}

EDIT: I don't know why, but the code is returning 2 more lines than the actual number of lines, for my solution, I just subtracted them before returning lineCount.

编辑:我不知道为什么,但代码返回的行比实际行数多 2 行,对于我的解决方案,我只是在返回 lineCount 之前减去它们。

回答by pejalo

The other answers here don't respect the numberOfLinesproperty of UILabelwhen it is set to something other than 0.

此处的其他答案不尊重将其设置为 0 以外的值的numberOfLines属性UILabel

Here's another option you can add to your category or subclass:

这是您可以添加到类别或子类的另一个选项:

- (NSUInteger)lineCount
{
    CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)];
    return MAX((int)(size.height / self.font.lineHeight), 0);
}

Some notes:

一些注意事项:

  • I'm using this on a UILabel with attributed text, without ever actually setting the fontproperty, and it's working fine. Obviously you would run into issues if you were using multiple fonts in your attributedText.
  • If you are subclassing UILabelto have custom edge insets (for example by overriding drawTextInRect:, which is a neat trick I found here), then you must remember to take those insets into account when calculating the sizeabove. For example: CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)
  • 我在带有属性文本的 UILabel 上使用它,而没有实际设置font属性,并且它工作正常。显然,如果您在attributedText.
  • 如果您将子类化为UILabel具有自定义边缘插入(例如通过覆盖drawTextInRect:,这是我在此处找到的一个巧妙技巧),那么您必须记住在计算size上述内容时考虑这些插入。例如:CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)

回答by Azharhussain Shaikh

Here is the Swift3 Codehere you can define Int value and get the height of text size by using (MAXFLOAT) and using that height you can get the total height of UILabel and by deviding that total height by character size you can get the actual line count of UILabel.

这是 Swift3 代码,您可以定义 Int 值并使用 (MAXFLOAT) 获取文本大小的高度,并使用该高度获取 UILabel 的总高度,并通过将总高度除以字符大小来获取实际行UILabel 的数量。

var lineCount: Int = 0
var textSize = CGSize(width: CGFloat(yourLabel.frame.size.width), height: CGFloat(MAXFLOAT))
var rHeight: Int = lroundf(yourLabel.sizeThatFits(textSize).height)
var charSize: Int = lroundf(yourLabel.font.leading)
lineCount = rHeight / charSize
print("No of lines: \(lineCount)")

回答by nburk

Following up on @Prince's answer, I now implemented a categoryon UILabelas follows (note that I corrected some minor syntax mistakes in his answer that wouldn't let the code compile):

对@王子的回答之后,我现在实现一个品类UILabel,如下所示(请注意,我纠正了他的回答一些小的语法错误,不会让代码编译):

UILabel+Util.h

UILabel+Util.h

#import <UIKit/UIKit.h>

@interface UILabel (Util)
- (NSInteger)lineCount;
@end

UILabel+Util.,

UILabel+Util.,

#import "UILabel+Util.h"

@implementation UILabel (Util)

- (NSInteger)lineCount
{
    // Calculate height text according to font
    NSInteger lineCount = 0;
    CGSize labelSize = (CGSize){self.frame.size.width, FLT_MAX};
    CGRect requiredSize = [self.text boundingRectWithSize:labelSize  options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: self.font} context:nil];

    // Calculate number of lines
    int charSize = self.font.leading;
    int rHeight = requiredSize.size.height;
    lineCount = rHeight/charSize;

    return lineCount;
}

@end

回答by Kaushik Movaliya

You can find the total number of line available in your custom label Please check this code...

您可以在自定义标签中找到可用的总行数请检查此代码...

NSInteger numberOfLines = [self lineCountForText:@"YOUR TEXT"];

- (int)lineCountForText:(NSString *) text
{
    UIFont *font = [UIFont systemFontOfSize: 15.0];
    int width=Your_LabelWidht;

    CGRect rect = [text boundingRectWithSize:CGSizeMake(width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin  attributes:@{NSFontAttributeName : font} context:nil];
    return ceil(rect.size.height / font.lineHeight);
}

回答by sam

It seems that the official developer website mentions one solution Counting Lines of Textin Objc. However, it assumes you have a reference to a text view configured with a layout manager, text storage, and text container. Unfortunately, UILabel doesn't expose those to us, so we need create them with the same configuration as the UILabel.

官方开发者网站上似乎提到了一种解决方案Counting Lines of Textin Objc。但是,它假设您有对配置了布局管理器、文本存储和文本容器的文本视图的引用。不幸的是,UILabel 不会向我们公开这些,因此我们需要使用与 UILabel 相同的配置创建它们。

I translated the Objc code to swift as following. It seems work well for me.

我将 Objc 代码翻译成 swift 如下。这对我来说似乎很有效。

extension UILabel {
    var actualNumberOfLines: Int {
        let textStorage = NSTextStorage(attributedString: self.attributedText!)
        let layoutManager = NSLayoutManager()
        textStorage.addLayoutManager(layoutManager)
        let textContainer = NSTextContainer(size: self.bounds.size)
        textContainer.lineFragmentPadding = 0
        textContainer.lineBreakMode = self.lineBreakMode
        layoutManager.addTextContainer(textContainer)

        let numberOfGlyphs = layoutManager.numberOfGlyphs
        var numberOfLines = 0, index = 0, lineRange = NSMakeRange(0, 1)

        while index < numberOfGlyphs {
            layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
            index = NSMaxRange(lineRange)
            numberOfLines += 1
        }
        return numberOfLines
    }
}

回答by Fernando Cardenas

Swift 5.2

斯威夫特 5.2

The main point to make it work for me was to call label.layoutIfNeeded()because I was using autoLayout, otherwise it doesnt work.

让它对我有用的要点是调用label.layoutIfNeeded()因为我使用的是autoLayout,否则它不起作用。

func actualNumberOfLines(label: UILabel) -> Int {
        // You have to call layoutIfNeeded() if you are using autoLayout
        label.layoutIfNeeded()

        let myText = label.text! as NSString

        let rect = CGSize(width: label.bounds.width, height: CGFloat.greatestFiniteMagnitude)
        let labelSize = myText.boundingRect(with: rect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: label.font as Any], context: nil)

        return Int(ceil(CGFloat(labelSize.height) / label.font.lineHeight))
    }

Credits to: https://gist.github.com/fuxingloh/ccf26bb68f4b8e6cfd02, which provided the solution in an older swift version, and for mentioning the importance of layoutIfNeeded().

归功于:https: //gist.github.com/fuxingloh/ccf26bb68f4b8e6cfd02,它在较旧的 swift 版本中提供了解决方案,并提到了 layoutIfNeeded() 的重要性。