如何findUILabel的行数
我使用wrap方法在UILabel中显示文本。 现在我想要findUILabel中有多less行。
如果有任何可能的方法来findUILabel的行数。
谢谢。
正如指出的,这篇文章涉及如何获得高度,而不是行数。 为了获得行数,
- 获得单个字母的高度,例如
@"A"
。 - 将string的高度除以上面1中得到的高度。
例如
CGFloat unitHeight = [@"A" heightForWidth:width usingFont:font]; CGFloat blockHeight = [text heightForWidth:width usingFont:font]; NSInteger numberOfLines = ceilf(blockHeight / unitHeight); // need to #include <math.h> for ^^^^^
从iOS 7开始,获得标签所需高度的方式发生了变化。 为了获得高度,你可以使用下面的代码:
NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; CGSize labelSize = (CGSize){width, FLT_MAX}; CGRect r = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font} context:context];
高度是r.size.height
。 请注意,必须提供font
。 为了方便起见,你可以把它放到NSString的类中,例如
@implementation NSString (HeightCalc) - (CGFloat)heightForWidth:(CGFloat)width usingFont:(UIFont *)font { NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; CGSize labelSize = (CGSize){width, FLT_MAX}; CGRect r = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: font} context:context]; return r.size.height; } @end
(做内存pipe理,如果不使用ARC,顺便说一句)。
对于iOS 6及以下版本:
比方说,你有一个UILabel *myLabel
,你想要找出标签的高度(通过一些调整,可以通过将高度除以取决于字体大小的适当数字来获得线的数量)。
UILabel *myLabel; CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:myLabel.frame.size lineBreakMode:UILineBreakModeWordWrap]; CGFloat labelHeight = labelSize.height;
希望有所帮助。 如果它不起作用,让我知道,我会进一步挖掘。 另外,未经testing的代码,但从参考工作。
对于一个更完整的例子,这里是我放在视图控制器的viewDidLoad:方法中的代码:
[super viewDidLoad]; UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(50,50,200,350)]; myLabel.numberOfLines = 0; myLabel.lineBreakMode = UILineBreakModeWordWrap; myLabel.text = @"This is some text in a UILabel which is long enough to wrap around the lines in said UILabel. This is a test, this is only a test."; [self.view addSubview:myLabel]; CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font constrainedToSize:myLabel.frame.size lineBreakMode:UILineBreakModeWordWrap]; CGFloat labelHeight = labelSize.height; NSLog(@"labelHeight = %f", labelHeight); [myLabel release];
NSLog的输出结果如下:
2010-11-15 18:25:27.817 so_labelheight[728:307] labelHeight = 126.000000
对于iOS7及以上版本, 官方认可的计算行数的方法是使用TextKit:
func numberOfLinesForString(string: String, size: CGSize, font: UIFont) -> Int { let textStorage = NSTextStorage(string: string, attributes: [NSFontAttributeName: font]) let textContainer = NSTextContainer(size: size) textContainer.lineBreakMode = .ByWordWrapping textContainer.maximumNumberOfLines = 0 textContainer.lineFragmentPadding = 0 let layoutManager = NSLayoutManager() layoutManager.textStorage = textStorage layoutManager.addTextContainer(textContainer) var numberOfLines = 0 var index = 0 var lineRange : NSRange = NSMakeRange(0, 0) for (; index < layoutManager.numberOfGlyphs; numberOfLines++) { layoutManager.lineFragmentRectForGlyphAtIndex(index, effectiveRange: &lineRange) index = NSMaxRange(lineRange) } return numberOfLines }
现在不build议使用-sizeWithFont:constrainedToSize:lineBreakMode
方法。 您将要使用方法-boundingRectWithSize:options:attributes:context:
now。
这里有一个例子:
CGSize boundingRectSize = CGSizeMake(widthToConstrainTo, CGFLOAT_MAX); NSDictionary *attributes = @{NSFontAttributeName : [UIFont fontWithName:fontName size:14]}; CGRect labelSize = [labelString boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil];
在上面的例子中,我知道我想限制标签的宽度,但是因为我不确定高度,所以我只是使用CGFLOAT_MAX
来CGFLOAT_MAX
高度参数。 对于需要使用NSStringDrawingUsesLineFragmentOrigin
和NSStringDrawingUsesFontLeading
的options
,如果你想要计算大小的标签可以是任意数量的行。
sizeWithFont
在iOS 7中已被弃用,您可以改为使用它:
- (int)lineCountForText:(NSString *) text { UIFont *font = ... CGRect rect = [text boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil]; return ceil(rect.size.height / font.lineHeight); }
如果你正在Swift 2 + / iOS 8中寻找这个答案,它会看起来像这样:
func numberOfLinesInLabel(yourString: String, labelWidth: CGFloat, labelHeight: CGFloat, font: UIFont) -> Int { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.minimumLineHeight = labelHeight paragraphStyle.maximumLineHeight = labelHeight paragraphStyle.lineBreakMode = .ByWordWrapping let attributes: [String: AnyObject] = [NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle] let constrain = CGSizeMake(labelWidth, CGFloat(Float.infinity)) let size = yourString.sizeWithAttributes(attributes) let stringWidth = size.width let numberOfLines = ceil(Double(stringWidth/constrain.width)) return Int(numberOfLines) }
(我最初在这里发布了我的答案,但没有足够的评论或重复的声誉。)
我发现的其他答案并不尊重UILabel
的numberOfLines
属性,当它被设置为0以外的东西。
这是另一个可以添加到您的类别或子类的选项:
- (NSUInteger)lineCount { CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)]; return MAX((int)(size.height / self.font.lineHeight), 0); }
一些说明:
- 我使用这个UILabel与归属文本,没有实际设置
font
属性,它工作正常。 显然,如果您在attributedText
文本中使用多种字体,则会遇到问题。 - 如果你将
UILabel
为自定义的边缘插入(例如,通过重写drawTextInRect:
这是我在这里find的一个巧妙的技巧),那么当计算上面的size
时,你必须记得考虑这些插入。 例如:CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)
func getHeight(text: NSString, width:CGFloat, font: UIFont) -> CGFloat { let rect = text.boundingRect(with: CGSize.init(width: width, height: CGFloat.greatestFiniteMagnitude), options: ([NSStringDrawingOptions.usesLineFragmentOrigin,NSStringDrawingOptions.usesFontLeading]), attributes: [NSFontAttributeName:font], context: nil) return rect.size.height }
文本:标签的高度,你需要find给定的string
宽度:UILabel的宽度
字体:UILabel的字体