Quiero calcular el número de líneas y la altura de UILabel de manera dinámica a partir de texto determinado para el mismo.

InformationsquelleAutor Hitesh | 2011-08-24

14 Comentarios

  1. 81

    Probar este

    //UILabel *myLabel;
    
    CGSize labelSize = [myLabel.text sizeWithFont:myLabel.font 
                                constrainedToSize:myLabel.frame.size 
                                    lineBreakMode:NSLineBreakByWordWrapping];
    
    CGFloat labelHeight = labelSize.height;
    
    
    int lines = [myLabel.text sizeWithFont:myLabel.font 
                         constrainedToSize:myLabel.frame.size 
                             lineBreakMode:NSLineBreakByWordWrapping].height/16; 
                 //'16' is font size

    o

    int lines = labelHeight/16;
    
    NSLog(@"lines count : %i \n\n",lines);  

    o

    int lines = [myLabel.text sizeWithFont:myLabel.font 
                         constrainedToSize:myLabel.frame.size 
                             lineBreakMode:UILineBreakModeWordWrap].height /myLabel.font.pointSize; //fetching font size from font

    Mediante el uso de Categorías, Acaba de Crear la categoría de clase denominada como

    UILabel+UILabelDynamicHeight.h

    UILabel+UILabelDynamicHeight.m

    No más tensión sobre el cálculo de altura. Por favor revise la siguiente aplicación.

    Actualizaciones para iOS7 & Arriba,el iOS 7 a continuación : calcular de forma Dinámica el UILabel altura

    #define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
    #define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
    #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
    #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
    #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
    #define iOS7_0 @"7.0"

    UILabel+UILabelDynamicHeight.h

    #import <UIKit/UIKit.h>
    @interface UILabel (UILabelDynamicHeight)
    
    #pragma mark - Calculate the size the Multi line Label
    /*====================================================================*/
    
        /* Calculate the size of the Multi line Label */
    
    /*====================================================================*/
    /**
     *  Returns the size of the Label
     *
     *  @param aLabel To be used to calculte the height
     *
     *  @return size of the Label
     */
     -(CGSize)sizeOfMultiLineLabel;
    
    @end

    UILabel+UILabelDynamicHeight.m

    #import "UILabel+UILabelDynamicHeight.h"
    @implementation UILabel (UILabelDynamicHeight)
    
    
    #pragma mark - Calculate the size,bounds,frame of the Multi line Label
    /*====================================================================*/
    
    /* Calculate the size,bounds,frame of the Multi line Label */
    
    /*====================================================================*/
    /**
     *  Returns the size of the Label
     *
     *  @param aLabel To be used to calculte the height
     *
     *  @return size of the Label
     */
    -(CGSize)sizeOfMultiLineLabel{
    
        //Label text
        NSString *aLabelTextString = [self text];
    
        //Label font
        UIFont *aLabelFont = [self font];
    
        //Width of the Label
        CGFloat aLabelSizeWidth = self.frame.size.width;
    
    
        if (SYSTEM_VERSION_LESS_THAN(iOS7_0)) {
            //version < 7.0
    
            return [aLabelTextString sizeWithFont:aLabelFont
                                constrainedToSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
                                    lineBreakMode:NSLineBreakByWordWrapping];
        }
        else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(iOS7_0)) {
            //version >= 7.0
    
            //Return the calculated size of the Label
            return [aLabelTextString boundingRectWithSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
                                                  options:NSStringDrawingUsesLineFragmentOrigin
                                               attributes:@{
                                                            NSFontAttributeName : aLabelFont
                                                            }
                                                  context:nil].size;
    
        }
    
        return [self bounds].size;
    
    }
    @end
    • pero, ¿cómo encontrar el número de líneas de la etiqueta?
    • 16 se usa para qué?
    • Yo había especificado en la primera secuencia de código. Por favor, eche un vistazo a «//16 es el tamaño de la fuente». Si el tamaño de la fuente difiere a continuación, el tamaño de la etiqueta debe ser más grande.Gran cosa a la que se necesita gran espacio en una habitación!!!
    • lo siento, a fuerza de mirar, de todos modos gracias a un código perfecto yo sólo era para +el + 1.
    • @Dhara 🙂 🙂 🙂
    • Gracias +1 para la solución a resolver mi problema y salvar a mi publicación de la aplicación 🙂
    • Feliz de ayudar:)
    • Este método está en desuso . en lugar de utilizar boundingRectWithSize:opciones:atributos:contexto
    • actualizado para iOS7
    • NSAssert(self, @»UILabel fue nulo»); Esto es ridículo. Si el auto fue nula, entonces no va a llegar, porque el envío de mensajes a nil no hacer nada.
    • de hecho el hombre. Anteriormente he usado este como método de clase,que permite el paso de la etiqueta para el método de enfoque diferente. he quitado esa línea.
    • Esto no es muy claro, está el cálculo de la etiqueta del tamaño de su tamaño de fotograma. Pero no sabemos la altura de la etiqueta que es lo que estamos buscando entonces, ¿cómo podemos especificar el tamaño en primera ?

  2. 52

    Llamar -sizeToFit en UILabel instancia cambiará de tamaño automáticamente para que se ajuste el texto que muestra, no el cálculo requerido. Si usted necesita el tamaño, usted puede conseguir a partir de la etiqueta de fotograma de la propiedad después de eso.

    label.numberOfLines = 0; //allows label to have as many lines as needed
    label.text = @"some long text";
    [label sizeToFit];
    NSLog(@"Label's frame is: %@", NSStringFromCGRect(label.frame));
    • Pero no restringir el ancho para beneficiar el diseño de interfaz de usuario.
    • se restringe el ancho de valor de la corriente que se establece antes de llamar -sizeToFit
    • A mi me funciona pero necesita ser intento de restricción de altura en la etiqueta, la necesidad de poner mayor o igual.
    • Se ahorra un montón de tiempo si usted recordar acerca de el .numberOfLines = 0 propiedad! Gracias!
    • También, usted tendrá que llamar a sizeToFit en viewDidLayoutSubviews en lugar de viewDidLoad.
  3. 30

    Para resumir, se puede calcular la altura de una etiqueta mediante el uso de su cadena y la llamada boundingRectWithSize. Usted debe proporcionar la font como un atributo, y se incluyen .usesLineFragmentOrigin para multi-línea de etiquetas.

    let labelWidth = label.frame.width
    let maxLabelSize = CGSize(width: labelWidth, height: CGFloat.greatestFiniteMagnitude)
    let actualLabelSize = label.text!.boundingRect(with: maxLabelSize, options: [.usesLineFragmentOrigin], attributes: [.font: label.font], context: nil)
    let labelHeight = actualLabelSize.height(withWidth:labelWidth)

    Algunas extensiones para hacer precisamente eso:

    Swift Versión:

    extension UILabel {
        func textHeight(withWidth width: CGFloat) -> CGFloat {
            guard let text = text else {
                return 0
            }
            return text.height(withWidth: width, font: font)
        }
    
        func attributedTextHeight(withWidth width: CGFloat) -> CGFloat {
            guard let attributedText = attributedText else {
                return 0
            }
            return attributedText.height(withWidth: width)
        }
    }
    
    extension String {
        func height(withWidth width: CGFloat, font: UIFont) -> CGFloat {
            let maxSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
            let actualSize = self.boundingRect(with: maxSize, options: [.usesLineFragmentOrigin], attributes: [.font : font], context: nil)
            return actualSize.height
        }
    }
    
    extension NSAttributedString {
        func height(withWidth width: CGFloat) -> CGFloat {
            let maxSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
            let actualSize = boundingRect(with: maxSize, options: [.usesLineFragmentOrigin], context: nil)
            return actualSize.height
        }
    }

    Objective-C Versión:

    UILabel+Utilidad.h

    #import <UIKit/UIKit.h>
    @interface UILabel (Utility)
    - (CGFloat)textHeightForWidth:(CGFloat)width;
    - (CGFloat)attributedTextHeightForWidth:(CGFloat)width;
    @end

    UILabel+Utilidad.m

    @implementation NSString (Utility)
    - (CGFloat)heightForWidth:(CGFloat)width font:(UIFont *)font {
        CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX);
        CGSize actualSize = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil].size;
        return actualSize.height;
    }
    @end
    
    @implementation NSAttributedString (Utility)
    - (CGFloat)heightForWidth:(CGFloat)width {
        CGSize maxSize = CGSizeMake(width, CGFLOAT_MAX);
        CGSize actualSize = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
        return actualSize.height;
    }
    @end
    
    @implementation UILabel (Utility)
    - (CGFloat)textHeightForWidth:(CGFloat)width {
        return [self.text heightForWidth:width font:self.font];
    }
    - (CGFloat)attributedTextHeightForWidth:(CGFloat)width {
        return [self.attributedText heightForWidth:width];
    }
    @end
    • Esto no funciona para mí.. pastebin.com/MJxPV7JX < – ¿Alguna idea?
    • Sin entrar en profundidad en el código, se podría decir que hay una buena probabilidad de que las etiquetas de fotograma/límites no es correcto en el tiempo que usted está tratando de medir. Si usted tiene a la medida, lo que podría forzar un layoutSubviews llamada llamando setNeedsLayout y layoutIfNeeded.
    • este podría ser modificado de modo que cuando el texto de una etiqueta incluye \n que se puede calcular correctamente?
    • Esto no funciona cuando uilabel es menor altura constante de texto puede tener lugar
  4. 17

    La solución actual se ha dejado de utilizarse a partir de iOS 7.

    Aquí es una solución actualizada:

    + (CGFloat)heightOfCellWithIngredientLine:(NSString *)ingredientLine
                           withSuperviewWidth:(CGFloat)superviewWidth
    {
        CGFloat labelWidth                  = superviewWidth - 30.0f;
        //   use the known label width with a maximum height of 100 points
        CGSize labelContraints              = CGSizeMake(labelWidth, 100.0f);
    
        NSStringDrawingContext *context     = [[NSStringDrawingContext alloc] init];
    
        CGRect labelRect                    = [ingredientLine boundingRectWithSize:labelContraints
                                                            options:NSStringDrawingUsesLineFragmentOrigin
                                                         attributes:nil
                                                            context:context];
    
        //   return the calculated required height of the cell considering the label
        return labelRect.size.height;
    }

    La razón por la que mi solución es configurar como este es porque estoy utilizando un UITableViewCell y el tamaño de la celda de forma dinámica en relación a la cantidad de espacio de la etiqueta tomarán.

    • no funciona para atribuido cadenas..
    • en lugar de enviar ‘nil’ pass ‘@{NSFontAttributeName:etiqueta.fuente}’ como atributos de
    • ¿Funciona con el iOS 6 también?
    • El método boundingRectWithSize:opciones:atributos:contexto: sólo está disponible en iOS 7 y versiones posteriores.
  5. 8

    Sin llamar sizeToFit, usted puede hacer esto de forma numérica con un muy plug and play:

    + (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width {
        CGSize size = [text sizeWithAttributes:@{NSFontAttributeName:font}];
        CGFloat area = size.height * size.width;
        CGFloat height = roundf(area / width);
        return ceilf(height / font.lineHeight) * font.lineHeight;
    }

    Yo lo uso mucho para UITableViewCells que tienen asignada dinámicamente a las alturas.

    Resuelve los atributos problema como bien @Salman Zaidi.

    • No funciona con NSMutableAttributedString y sin llamar sizeToFit, le da a la misma altura todo el tiempo.
    • Prueba esta sencilla UILabel fuente: Apple SD Gótico, Neo. No funciona.
    • Funciona muy bien, gracias
  6. 6

    Copy & paste este método & utilizado como:

    [lblText setFrame:CGRectMake(lblText.frame.origin.x, lblText.frame.origin.y, width, [self getLabelHeight:lblText])];
    
     - (CGFloat)getLabelHeight:(UILabel*)label
        {
            CGSize constraint = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);
            CGSize size;
    
            NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
            CGSize boundingBox = [label.text boundingRectWithSize:constraint
                                                          options:NSStringDrawingUsesLineFragmentOrigin
                                                       attributes:@{NSFontAttributeName:label.font}
                                                          context:context].size;
    
            size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
    
            return size.height;
        }
    • Hola @saraman, Si copiar y pegar a continuación el código también, favor de citar la fuente del código.
  7. 4
    CGSize maxSize = CGSizeMake(lbl.frame.size.width, CGFLOAT_MAX);
    CGSize requiredSize = [lbl sizeThatFits:maxSize];
    CGFloat height=requiredSize.height
  8. 1

    Usted necesita para crear una extensión de la Cadena y llamar a este método

    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
        return ceil(boundingBox.height)
    }

    Debe enviar el ancho de la etiqueta

  9. 1

    Swift 4 Para llegar a la altura de los NSAttributedString utilizar esta función a continuación. Donde ancho – la anchura de su UILabel o UITextView

    func getHeight(for attributedString: NSAttributedString, font: UIFont, width: CGFloat) -> CGFloat {
        let textStorage = NSTextStorage(attributedString: attributedString)
        let textContainter = NSTextContainer(size: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude))
        let layoutManager = NSLayoutManager()
        layoutManager.addTextContainer(textContainter)
        textStorage.addLayoutManager(layoutManager)
        textStorage.addAttribute(NSAttributedStringKey.font, value: font, range: NSMakeRange(0, textStorage.length))
        textContainter.lineFragmentPadding = 0.0
        layoutManager.glyphRange(for: textContainter)
        return layoutManager.usedRect(for: textContainter).size.height
    }

    Para obtener la altura de Cadena utilizar esta función, es casi idéntico al igual que el anterior método:

    func getHeight(for string: String, font: UIFont, width: CGFloat) -> CGFloat {
        let textStorage = NSTextStorage(string: string)
        let textContainter = NSTextContainer(size: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude))
        let layoutManager = NSLayoutManager()
        layoutManager.addTextContainer(textContainter)
        textStorage.addLayoutManager(layoutManager)
        textStorage.addAttribute(NSAttributedStringKey.font, value: font, range: NSMakeRange(0, textStorage.length))
        textContainter.lineFragmentPadding = 0.0
        layoutManager.glyphRange(for: textContainter)
        return layoutManager.usedRect(for: textContainter).size.height
    }
  10. 0

    En mi caso, yo estaba usando un fija el tamaño de la cabecera para cada sección, pero con un dinámicamente el tamaño de la celda en cada encabezado.
    La célula de la altura, depende de la etiqueta de la altura.

    De trabajo con:

    tableView.estimatedRowHeight = SomeNumber
    tableView.rowHeight = UITableViewAutomaticDimension

    Obras pero cuando se usa:

    tableView.reloadSections(IndexSet(integer: sender.tag) , with: .automatic)

    cuando una gran cantidad de encabezados no se contraen, se crea una gran cantidad de insectos como encabezado de la duplicación (tipo de encabezado x debajo del mismo tipo) y raro animaciones de cuando el marco se vuelve a cargar con la animación, incluso cuando se utiliza con el tipo .none (FYI, un encabezado fijo altura y la altura de las células obras).

    La solución es hacer que el uso de heightForRowAt de devolución de llamada y calcular la altura de la etiqueta de su auto (además de la animación se ve mucho mejor). Recuerde que la altura se llama primera.

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
    {
        let object = dataDetailsController.getRowObject(forIndexPath: indexPath)
        let label = UILabel(frame: tableView.frame)
        let font = UIFont(name: "HelveticaNeue-Bold", size: 25)
        label.text = object?.name
        label.font = font
        label.numberOfLines = 0
        label.textAlignment = .center
        label.sizeToFit()
        let size = label.frame.height
        return Float(size) == 0 ? 34 : size
    }
  11. 0

    Esta es la extensión que yo uso para el cálculo de varias líneas UILabel alturas, es ajustar el fragmento de código anterior en un desbordamiento de pila post:

    extension UILabel {
        func estimatedHeight(forWidth: CGFloat, text: String, ofSize: CGFloat) -> CGFloat {
    
            let size = CGSize(width: forWidth, height: CGFloat(MAXFLOAT))
    
            let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    
            let attributes = [NSFontAttributeName: UIFont.systemFont(ofSize: ofSize)]
    
            let rectangleHeight = String(text).boundingRect(with: size, options: options, attributes: attributes, context: nil).height
    
            return ceil(rectangleHeight)
        }
    }
  12. 0

    Si usted está usando un UILabel con atributos, usted puede probar el método de textRect(forBounds:limitedToNumberOfLines).

    Este es mi ejemplo:

    let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
    label.numberOfLines = 0
    label.text = "Learn how to use RxSwift and RxCocoa to write applications that can react to changes in your underlying data without you telling it to do so."
    
    let rectOfLabel = label.textRect(forBounds: CGRect(x: 0, y: 0, width: 100, height: CGFloat.greatestFiniteMagnitude), limitedToNumberOfLines: 0)
    let rectOfLabelOneLine = label.textRect(forBounds: CGRect(x: 0, y: 0, width: 100, height: CGFloat.greatestFiniteMagnitude), limitedToNumberOfLines: 1)
    let heightOfLabel = rectOfLabel.height
    let heightOfLine = rectOfLabelOneLine.height
    let numberOfLines = Int(heightOfLabel / heightOfLine)

    Y mis resultados en el Patio de recreo:

    Cómo calcular UILabel altura de forma dinámica?

  13. -1

    Para hacer UILabel ajuste el contenido dinámico puede utilizar las líneas de propiedad en el inspector de propiedades y establecer que como 0.

    Y no se requieren para realizar cualquier tipo de codificación para esto.

    Para más detalles se puede comprobar a continuación un video con una demostración

    https://www.youtube.com/watch?v=rVeDS_OGslU

  14. -2

    si desea que la etiqueta de tomar las líneas dinámicas, usted puede utilizar este

    label.numberOfLines = 0; //allows label to have as many lines as needed
    label.text = @"some long text ";
    [label sizeToFit];
    NSLog(@"Label's frame is: %@", NSStringFromCGRect(label.frame));

Dejar respuesta

Please enter your comment!
Please enter your name here