2010-11-13 10 views
39

Mostré el texto en UILabel utilizando el método de ajuste. Ahora quiero encontrar la cantidad de líneas que hay en UILabel.Cómo encontrar el número de líneas de UILabel

Si hay alguna forma de encontrar el número de líneas de UILabel, cuente.

Gracias.

+0

http://stackoverflow.com/questions/4082041/resulting-lines-of-uilabel-with-uilinebreakmodewordwrap/14401282#14401282 – TheTiger

Respuesta

50

Como se señaló, esta publicación se refiere a cómo obtener la altura, en lugar de la cantidad de líneas. Para obtener el número de líneas,

  1. Obtenga la altura para una sola letra, p. @"A".
  2. Divide la altura de la cuerda por la altura obtenida en 1 arriba.

E.g.

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 ^^^^^ 

A partir de iOS 7, el camino de conseguir la altura deseada de una etiqueta cambiado. Para obtener la altura, puede utilizar el siguiente código:

donde la altura es r.size.height. Tenga en cuenta que se debe proporcionar font. Puede poner esto en una categoría para NSString por conveniencia, p.

@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 

(Hacer la gestión de memoria si no se usa ARC, por cierto.)

Para iOS 6 y abajo:

Digamos que usted tiene un UILabel *myLabel y quiere averiguar la altura de la etiqueta (con algunos ajustes, puede obtener el número de líneas dividiendo la altura con un número apropiado que depende del tamaño de la fuente).

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

Espero que ayude. Si no funciona, házmelo saber y profundizaré más. Además, código no probado, pero funcionó a partir de la referencia.

Para un ejemplo más completo, aquí es el código que puse en el viewDidLoad: método de un controlador de vista:

[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]; 

La salida del NSLog va:

2010-11-15 18:25:27.817 so_labelheight[728:307] labelHeight = 126.000000 
+0

muestra los siguientes dos errores // error: tipo incompatible para el argumento 2 de 'sizeWithFont: constrainedToSize : lineBreakMode:' \t \t \t error: solicitud de miembro de 'tamaño' en algo que no es una estructura o unión – Velmurugan

+0

por supuesto .size no es una propiedad en la UILabel, pero probablemente debería ser algo así como myLabel.frame.size o myLabel .bounds.size (no estoy seguro de cuál quiere). –

+0

Ah sí, se perdió ese. Gracias Wim H. Resolvió el ejemplo anterior para usar frame.size. – Kalle

7

El método -sizeWithFont:constrainedToSize:lineBreakMode ahora está en desuso Deseará utilizar el método -boundingRectWithSize:options:attributes:context: ahora.

He aquí un ejemplo:

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]; 

En el ejemplo anterior Sé el ancho quiero restringir la etiqueta, pero ya no estoy seguro de la altura, acabo máximo la altura parámetro cabo utilizando CGFLOAT_MAX . Para el options necesita usar NSStringDrawingUsesLineFragmentOrigin y NSStringDrawingUsesFontLeading si está tratando de calcular el tamaño de una etiqueta que puede ser cualquier cantidad de líneas.

6

sizeWithFont está en desuso en iOS 7, es posible utilizar esto en su lugar:

- (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); 
} 
13

Para iOS7 y por encima, el officially sanctioned way para contar el número de líneas es utilizar 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 
} 
2

(Originalmente publiqué mi respuesta here pero no tengo suficiente reputación para comentar o marcar duplicados.)

Las otras respuestas I'v e encontrados no respetar la propiedad de numberOfLinesUILabel cuando está ajustado a algo distinto de 0.

Aquí hay otra opción que puede agregar a su categoría o subclase:

- (NSUInteger)lineCount 
{ 
    CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)]; 
    return MAX((int)(size.height/self.font.lineHeight), 0); 
} 

Algunas notas:

  • Estoy usando esto en un UILabel con texto atribuido, sin establecer realmente la propiedad font, y está funcionando bien. Obviamente, se encontraría con problemas si estuviera usando varias fuentes en su attributedText.
  • Si está subclassing UILabel que tienen inserciones de borde personalizado (por ejemplo reemplazando drawTextInRect:, que es un buen truco que encontré here), entonces hay que acordarse de tomar esas inserciones en cuenta al calcular la size anteriormente. Por ejemplo: CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)
5

Si usted está buscando esta respuesta en Swift 2 +/iOS 8, que se vería así:

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) 
} 
+0

Esta respuesta es buena desde iOS8 –

+0

Gracias @AvielGross. Editado para reflejar su entrada. – cph2117

+0

¿Cuál es el propósito de "restringir" aquí? –

0
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 
} 

texto: el sello cuya altura que necesita de encontrar con la cadena dada

ancho: el ancho de UILabel

fuente: la fuente de UILabel

Cuestiones relacionadas