用a和a初始化后,如何找到a的实际行数?我将其属性设置为,因此它将扩展为需要很多行。但是,然后,如何确定设置后最终得到的行数呢?UILabel
text
font
numberOfLines
0
text
我发现了类似的问题,但似乎没有一个简单的答案,而且在我看来,必须很容易就可以轻松获得它,而不必在处理boundingRectWithSize
or或sizeWithFont
...时产生任何开销。
Answers:
第一选择:
首先根据字体计算文字的高度:
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);
The leading value represents additional space between lines of text and is measured in points.
(developer.apple.com/reference/uikit/uifont/1619026-leading)。
boundingRectWithSize
是NSString的一种方法。
lineHeight
确实有效,leading
但无效(至少对我而言)。更新了答案
这些都不对我有用。不到一个,
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
}
}
斯威夫特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
}
}
斯威夫特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
}
}
frame.size.width
有时返回0,并且给出错误的maxSize并基于该textSize。以我UIScreen.main.bounds.width
为例,将width设置为maxSize解决了问题
迅捷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))
为我计算正确的线
这是@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
}
编辑:我不知道为什么,但是代码返回的行数比实际的行数多2条,对于我的解决方案,我只是在返回lineCount之前减去了它们。
这里的其他答案不尊重numberOfLines
的财产UILabel
设置为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
具有自定义边缘插图(例如,通过overriding 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)")
似乎官方开发人员网站提到了Objc中一种计算文本行数的解决方案。但是,它假定您对配置了布局管理器,文本存储和文本容器的文本视图有引用。不幸的是,UILabel并未向我们公开这些内容,因此我们需要使用与UILabel相同的配置来创建它们。
我将Objc代码翻译如下。对我来说似乎不错。
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
}
}
对@王子的回答之后,我现在实现一个品类上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
leading
内容为“lineHeight
改为使用该属性”。事实上,在我的UILabel
,字体的leading
属性等于0
您可以在自定义标签中找到可用的行总数。请检查此代码...
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);
}
迅捷5.2
使它对我有用的主要点是调用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))
}
感谢:https : //gist.github.com/fuxingloh/ccf26bb68f4b8e6cfd02,它以较早的swift版本提供了解决方案,并提到了layoutIfNeeded()的重要性。
请注意,@ kurt-j的答案并不总是有效。在某些情况下,您将必须手动提供标签的宽度。由于存在这些情况,因此即使您最终不使用它,也最好有一个可选的width参数。
Swift 4.2:
extension UILabel {
func calculateMaxLines(actualWidth: CGFloat?) -> Int {
var width = frame.size.width
if let actualWidth = actualWidth {
width = actualWidth
}
let maxSize = CGSize(width: 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
}
}
Xamarin.iOS
感谢以上每个人提供的答案。
这将获得可见线的数量。
public static int VisibleLineCount(this UILabel label)
{
var textSize = new CGSize(label.Frame.Size.Width, nfloat.MaxValue);
nfloat rHeight = label.SizeThatFits(textSize).Height;
nfloat charSize = label.Font.LineHeight;
return Convert.ToInt32(rHeight / charSize);
}
这将获取文本将在屏幕上占据的实际行数。
public static int LineCount(this UILabel label)
{
var maxSize = new CGSize(label.Frame.Size.Width, nfloat.MaxValue);
var charSize = label.Font.LineHeight;
var text = (label.Text ?? "").ToNSString();
var textSize = text.GetBoundingRect(maxSize, NSStringDrawingOptions.UsesLineFragmentOrigin, new UIStringAttributes() { Font = label.Font }, null);
return Convert.ToInt32(textSize.Height / charSize);
}
我发现一个对我的用例有用的辅助方法。
public static bool IsTextTruncated(this UILabel label)
{
if (label.Lines == 0)
{
return false;
}
return (label.LineCount() > label.Lines);
}
要获得更准确的行数:
font.lineHeight
代替font.pointSize
let l = UILabel()
l.numberOfLines = 0
l.layer.frame.size.width = self.view.frame.width - 40 /*padding(20 + 20)*/
l.font = UIFont(name: "BwModelica-Bold", size: 16.0)
l.text = "Random Any length Text!!"
let noOfLines = ceil(l.intrinsicContentSize.width) / l.frame.width)
let lbl_height = noOfLines * l.intrinsicContentSize.height
这将是“标签”和“行数”的确切动态高度。编码愉快!
Nor️也不行,单靠单行也是不够的。lineHeight
leading
的font.lineHeight
是字形的高度,它跨越了从descender
(最低字形的底部)到ascender
(最高字形的顶部)。另外,请注意,lineHeight
可以覆盖属性字符串。的font.leading
是(!)行之间的额外空格(尽管可能是负数)(请参阅文档)。如果使用系统字体,几乎每个磅值都会得到不同的前导值。
因此,例如,具有5条线的标签的高度由5lineHeight
和4组成leading
(但是,前导值通常足够小,以至于上述解决方案可以起作用,直到开始使用多条线为止。
因此正确的(伪)公式应为:
(frame.size.height + font.leading) / (font.lineHeight + font.leading)
另外,如果属性字符串的附件太大(比
ascender
字体的附件大),则它还会更改该行的行高。