在我使用text
和font
初始化了一个UILabel
后,如何找到它实际的行数?我已经将它的numberOfLines
属性设置为0
,以便它可以扩展为所需的行数。但是,如何找出我设置它的text
后最终得到了多少行?
我找到了类似的问题,但没有一个提供简洁答案的,在我的看来,获取它而不需要使用boundingRectWithSize
或sizeWithFont
等方式是非常容易的...
这些方法都对我没用。下面这个方法有效:
Swift 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:
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:
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
}
}
Swift 5 (IOS 12.2)
获取标签渲染文本所需的最大行数,以避免截断。
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))
}
}
在限定边界内,获取标签可显示的最大行数。在将文本分配给标签后使用此属性。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))
}
}
使用方法
print(yourLabel.maxNumberOfLines)
print(yourLabel.numberOfVisibleLines)
let zone = CGSize(width: intrinsicContentSize.width, height: CGFloat(MAXFLOAT)) let fittingHeight = Float(self.sizeThatFits(zone).height) return lroundf(fittingHeight / Float(font.lineHeight))
此代码用于计算正确的行数。 - Azules第一个选项:
首先根据字体计算文本高度:
NSInteger lineCount = 0;
CGSize labelSize = (CGSize){yourLabel.frame.size.width, MAXFLOAT};
CGRect requiredSize = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: yourLabel.font} context:nil];
现在计算行数:
int charSize = lroundf(yourLabel.font.lineHeight);
int rHeight = lroundf(requiredSize.height);
lineCount = rHeight/charSize;
NSLog(@"No of lines: %i",lineCount);
第二个选项:
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);
领先值代表文本行之间的额外间距,以点为单位测量。
(https://developer.apple.com/reference/uikit/uifont/1619026-leading) - Chris PrincelineHeight
确实有效,而 leading
不行(至少对我来说是这样)。回答已更新。 - yonix这是@Paresh解决方案的Swift版本:
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
}
编辑:我不知道为什么,但是这段代码返回的行数比实际行数多了2行,对于我的解决方案,我只需在返回lineCount之前减去它们。
Swift 5.2
对于我而言,让它起作用的关键是调用 label.layoutIfNeeded() ,因为我正在使用自动布局,否则它不起作用。
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))
}
致谢:https://gist.github.com/fuxingloh/ccf26bb68f4b8e6cfd02,提供了旧版本Swift的解决方案,并提到了layoutIfNeeded()的重要性。
return Int(ceil(CGFloat(labelSize.height) / font.lineHeight))
}
- BunthoeunUILabel
的numberOfLines
属性被设置为0以外的值时,这个属性是什么。- (NSUInteger)lineCount
{
CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)];
return MAX((int)(size.height / self.font.lineHeight), 0);
}
一些注意事项:
font
属性,它正常工作。显然,如果您在您的 attributedText
中使用了多种字体,则可能会遇到问题。UILabel
以具有自定义的边缘插图(例如通过覆盖 drawTextInRect:
,这是我在 这里 找到的一种巧妙技巧),则必须记住在计算上面的 size
时考虑这些插图。例如:CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)
这里是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)")
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
}
}
您可以找到自定义标签中可用行的总数。 请查看此代码...
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);
}
在@Prince的回答基础上,我现在按照以下方式在UILabel
上实现了一个类别(请注意,我纠正了他的回答中一些语法错误,这些错误会导致代码无法编译):
#import <UIKit/UIKit.h>
@interface UILabel (Util)
- (NSInteger)lineCount;
@end
#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
lineHeight
属性代替。” 实际上,在我的UILabel
上,字体的“leading”属性等于0。 - Gerard
frame.size.width
有时会返回0,导致maxSize不正确,进而影响到textSize。在我的情况下,将UIScreen.main.bounds.width
设置为maxSize解决了这个问题。 - lmboom