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
How to find actual number of lines of UILabel?
提问by nburk
How can I find the actualnumber of lines of a UILabel
after I have initialized it with a text
and a font
? I have set its numberOfLines
property 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 的实际行数?我已将其属性设置为,因此它将扩展为需要多行。但是,在我设置它之后,我怎样才能知道它最终得到了多少行呢?UILabel
text
font
numberOfLines
0
text
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 boundingRectWithSize
or sizeWithFont
,...
我发现了类似的问题,但似乎没有一个提供简洁的答案,在我看来,它必须很容易得到它,而无需处理boundingRectWithSize
or 的任何开销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 numberOfLines
property of UILabel
when 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
font
property, and it's working fine. Obviously you would run into issues if you were using multiple fonts in yourattributedText
. - If you are subclassing
UILabel
to have custom edge insets (for example by overridingdrawTextInRect:
, which is a neat trick I found here), then you must remember to take those insets into account when calculating thesize
above. 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 UILabel
as 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() 的重要性。