Как узнать количество строк UILabel - PullRequest
40 голосов
/ 13 ноября 2010

Я отобразил текст в UILabel, используя метод переноса. Теперь я хочу узнать, сколько строк в UILabel.

Если есть какой-либо возможный способ узнать количество строк UILabel.

Спасибо.

Ответы [ 7 ]

50 голосов
/ 13 ноября 2010

Как уже указывалось, этот пост описывает, как получить высоту, а не количество строк. Чтобы получить количество строк,

  1. Получите высоту для одной буквы, например, @"A".
  2. Разделите высоту строки на высоту, полученную в 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

(управление памятью, если не используется ARC, кстати.)

Для iOS 6 и ниже:

Допустим, у вас есть UILabel *myLabel, и вы хотите узнать высоту метки (с некоторыми изменениями вы можете получить количество строк, разделив высоту на некоторое соответствующее число, которое зависит от размера шрифта).

UILabel *myLabel;
CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font 
                            constrainedToSize:myLabel.frame.size 
                                lineBreakMode:UILineBreakModeWordWrap];
CGFloat labelHeight = labelSize.height;

Надеюсь, это поможет. Если это не сработает, дайте мне знать, и я буду копать дальше. Также, непроверенный код, но работал по ссылке.

Для более полного примера, вот код, который я поместил в 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
14 голосов
/ 05 мая 2015

Для 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
}
7 голосов
/ 04 июля 2014

Метод -sizeWithFont:constrainedToSize:lineBreakMode устарел.Вы захотите использовать метод -boundingRectWithSize:options:attributes:context: сейчас.

Вот примеры:

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.Для options вам нужно использовать NSStringDrawingUsesLineFragmentOrigin и NSStringDrawingUsesFontLeading, если вы пытаетесь вычислить размер метки, который может быть любым числом строк.

6 голосов
/ 14 декабря 2015

Если вы ищете этот ответ в 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)
}
6 голосов
/ 23 августа 2014

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);
}
2 голосов
/ 03 июня 2015

(я первоначально разместил свой ответ здесь , но у меня недостаточно репутации, чтобы комментировать или отмечать дубликаты.)

Другие ответы, которые я нашел, не относятся к свойству 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);
}

Некоторые заметки:

  • Я использую это на UILabel с атрибутивным текстом, фактически не устанавливая свойство font, и оно работает нормально. Очевидно, вы столкнетесь с проблемами, если будете использовать несколько шрифтов в своем attributedText.
  • Если вы создаете подклассы UILabel для создания пользовательских ребер-вставок (например, путем переопределения drawTextInRect:, что я обнаружил здесь ), то вы должны помнить, чтобы эти вставки учитывались при расчете size выше. Например: CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)
0 голосов
/ 19 сентября 2017
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
}

текст: метка, высота которой вам нужно найти с заданной строкой

ширина: ширина UILabel

шрифт: шрифт UILabel

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...