Ajustar la altura de UILabel al texto


112

Tengo algunas etiquetas que quiero ajustar su altura al texto, este es el código que escribí para esto ahora

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height
}

EDITAR:

El problema no estaba en este código, por lo que mi solución está en la pregunta en sí. ¡Todavía podría ser útil para otros!


Eche un vistazo a las adiciones de NSString UIKit, existen métodos para calcular el tamaño que necesita sin crear un UILabel.
Vladimir Gritsenko

@VladimirGritsenko los métodos 'sizeWithFont' no están disponibles en Swift :(
TheBurgerShot

Admito que no soy un experto en Swift, pero creo que puede agregar sus propios métodos de puente. Todavía valdría la pena sobre la creación de UILabel para calcular el tamaño.
Vladimir Gritsenko

Es sizeWithFontposible que @TheBurgerShot no esté disponible para Swift, Stringpero está disponible en NSString. Debería poder llamarlo así.
Anorak

Al final, el error fue algo diferente y no tuvo nada que ver con este método. Aunque esto podría ser útil para otros.
TheBurgerShot

Respuestas:


189

Acabo de poner esto en un patio de recreo y funciona para mí.

Actualizado para Swift 4.0

import UIKit

 func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height
}

let font = UIFont(name: "Helvetica", size: 20.0)

var height = heightForView("This is just a load of text", font: font, width: 100.0)

Swift 3:

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()

    return label.frame.height
}

ingrese la descripción de la imagen aquí


esto también funciona bien para mí en el patio de recreo, el error no parece ocurrir en este lugar específico, cuando elimino los usos de este método, se quejará de algunos println o solo una línea con solo comentarios (luego dice EXC_BAD_ACCESS code = 2 también)
TheBurgerShot

6
Funciona en un patio de recreo, pero no se produce el tamaño deseado dentro de un controlador de vista en XCode 6.1
Unome

1
Estoy un poco reacio a crear una nueva UILabelpor talla; Si este método se utiliza en el interior layoutSubviewscon la tendencia a ser invocado varias veces por diseño completo, la creación de objetos adicionales puede introducir retrasos notables, especialmente durante el desplazamiento.
Zorayr

let textRect = textString.boundingRectWithSize (CGSizeMake (320, 2000), opciones: .UsesLineFragmentOrigin, atributos: textAttributes, contexto: nulo)
Siddharth Pancholi

No puedo llamar a esta función en mi controlador de vista ... ¿Puede sugerirme cuál podría ser la posible razón?
Rouny

64

Si está utilizando AutoLayout , puede ajustar la UILabelaltura solo mediante la interfaz de usuario de configuración.

Para iOS8 o superior

  • Establezca la restricción inicial / final para su UILabel
  • Y cambia las lineas de UILabel1 a 0

ingrese la descripción de la imagen aquí

Para iOS7

  • Primero , debe agregar contiene altura paraUILabel
  • Luego , modifique la Relación de EqualaGreater than or Equal

ingrese la descripción de la imagen aquí

  • Finalmente , cambia las líneas de UILabel1 a 0

ingrese la descripción de la imagen aquí

Su UILabelaumentará automáticamente dependiendo de la altura del texto


2
Y si la etiqueta está dentro de una celda. ¿Cuándo y cómo aumentaría la altura de la celda en consecuencia?
oyalhi

1
@oyalhi, si su etiqueta está dentro de una celda de vista de tabla, consulte mi otra publicación stackoverflow.com/a/36277840/5381331
Phan Van Linh

3
¡Esto funcionó perfectamente para mí! ¡Configure las restricciones y funcionará correctamente!
Bill Thompson

2
no funciona para mí ... la palabra "Etiqueta" en un UILabel hace altura = 20. Sigue siendo 20 después de este ajuste.
gadget00

9

Creo esta extensión si quieres

extension UILabel {
    func setSizeFont (sizeFont: CGFloat) {
        self.font =  UIFont(name: self.font.fontName, size: sizeFont)!
        self.sizeToFit()
    }
}

8

Tengo una fuerte solución de trabajo.

en diseño

    _title.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 0)
    _title.sizeToFit()
    _title.frame.size = _title.bounds.size

en establecedor de texto:

    _title.text = newValue
    setNeedsLayout()

UPD. por supuesto con esta configuración de UILabel:

    _title.lineBreakMode = .ByWordWrapping
    _title.numberOfLines = 0

6

Solo configurando:

label.numberOfLines = 0

La etiqueta ajusta automáticamente su altura según la cantidad de texto ingresado.


27
Esto no hace que el UILabel ajuste su altura.
TheBurgerShot

6

basado en la respuesta de Anorak, también estoy de acuerdo con la preocupación de Zorayr, así que agregué un par de líneas para eliminar el UILabel y devolver solo el CGFloat, no sé si ayuda ya que el código original no agrega el UIabel, pero no arroja error, así que estoy usando el siguiente código:

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{

    var currHeight:CGFloat!

    let label:UILabel = UILabel(frame: CGRectMake(0, 0, width, CGFloat.max))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.ByWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()

    currHeight = label.frame.height
    label.removeFromSuperview()

    return currHeight
}

5

En swift 4.1 y Xcode 9.4.1

Solo 3 pasos

Paso 1)

//To calculate height for label based on text size and width
func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat {
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height
}

Paso 2)

//Call this function
let height = heightForView(text: "This is your text", font: UIFont.systemFont(ofSize: 17), width: 300)
print(height)//Output : 41.0

Paso 3)

//This is your label
let proNameLbl = UILabel(frame: CGRect(x: 0, y: 20, width: 300, height: height))
proNameLbl.text = "This is your text"
proNameLbl.font = UIFont.systemFont(ofSize: 17)
proNameLbl.numberOfLines = 0
proNameLbl.lineBreakMode = .byWordWrapping
infoView.addSubview(proNameLbl)

5

La solución sugerida por Anorak como una propiedad calculada en una extensión para UILabel:

extension UILabel
{
var optimalHeight : CGFloat
    {
        get
        {
            let label = UILabel(frame: CGRectMake(0, 0, self.frame.width, CGFloat.max))
            label.numberOfLines = 0
            label.lineBreakMode = self.lineBreakMode
            label.font = self.font
            label.text = self.text

            label.sizeToFit()

            return label.frame.height
         }
    }
}

Uso:

self.brandModelLabel.frame.size.height = self.brandModelLabel.optimalHeight

¡Buena solución! Gracias :-)
Cristina

No se puede asignar a la propiedad: 'altura' es una propiedad de solo obtención.
Amg91

4

Siguiendo la respuesta de @Anorak, agregué esta extensión a String y envié un recuadro como parámetro, porque muchas veces necesitará un relleno en su texto. De todos modos, quizás a algunos les resulte útil.

extension String {

    func heightForWithFont(font: UIFont, width: CGFloat, insets: UIEdgeInsets) -> CGFloat {

        let label:UILabel = UILabel(frame: CGRectMake(0, 0, width + insets.left + insets.right, CGFloat.max))
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.ByWordWrapping
        label.font = font
        label.text = self

        label.sizeToFit()
        return label.frame.height + insets.top + insets.bottom
    }
}

label.lineBreakMode = NSLineBreakMode.ByWordWrapping esta línea me ayudó gracias.
Coder_A_D

3

A continuación se explica cómo calcular la altura del texto en Swift. Luego puede obtener la altura del rect y establecer la altura de restricción de la etiqueta o textView, etc.

let font = UIFont(name: "HelveticaNeue", size: 25)!
let text = "This is some really long text just to test how it works for calculating heights in swift of string sizes. What if I add a couple lines of text?"

let textString = text as NSString

let textAttributes = [NSFontAttributeName: font]

let textRect = textString.boundingRectWithSize(CGSizeMake(320, 2000), options: .UsesLineFragmentOrigin, attributes: textAttributes, context: nil)

3

simplemente llame a este método donde necesita una altura dinámica para la etiqueta

func getHeightforController(view: AnyObject) -> CGFloat {
    let tempView: UILabel = view as! UILabel
    var context: NSStringDrawingContext = NSStringDrawingContext()
    context.minimumScaleFactor = 0.8

    var width: CGFloat = tempView.frame.size.width

    width = ((UIScreen.mainScreen().bounds.width)/320)*width

    let size: CGSize = tempView.text!.boundingRectWithSize(CGSizeMake(width, 2000), options:NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: tempView.font], context: context).size as CGSize

    return size.height
}

3

Swift 4.0

self.messageLabel = UILabel (marco: CGRect (x: 70, y: 60, ancho: UIScreen.main.bounds.width - 80, alto: 30)

messageLabel.text = message

messageLabel.lineBreakMode = .byWordWrapping //in versions below swift 3 (messageLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping)    
messageLabel.numberOfLines = 0 //To write any number of lines within a label scope

messageLabel.textAlignment = .center

messageLabel.textColor = UIColor.white

messageLabel.font = messageLabel.font.withSize(12)

messageLabel.sizeToFit()

Blockquote NSParagraphStyle.LineBreakMode, se aplica a párrafos completos, no a palabras dentro de párrafos. Esta propiedad está en vigor tanto durante el dibujo normal como en los casos en que el tamaño de fuente debe reducirse para que quepa el texto de la etiqueta en su cuadro delimitador. Esta propiedad está establecida en byTruncatingTail de forma predeterminada.

Este enlace describe la forma del guión gráfico de hacer lo mismo


2
Las respuestas de solo código no se consideran una buena práctica. Considere agregar algunas explicaciones sobre cómo su respuesta aborda la pregunta.
Yannis

2

Swift 4.0

En lugar de calcular la altura del texto / etiqueta, simplemente cambio el tamaño de la etiqueta después de insertar el texto (dinámico).

Suponiendo que myLabel es el UILabel en cuestión:

let myLabel = UILabel(frame: CGRect(x: 0, y: 0, width: *somewidth*, height: *placeholder, e.g. 20*))
myLabel.numberOfLines = 0
myLabel.lineBreakMode = .byWordWrapping
...

Y ahora viene la parte divertida:

var myLabelText: String = "" {
   didSet {
      myLabel.text = myLabelText
      myLabel.sizeToFit()
   }
}

2

El método de extensión Swift 4.1 para calcular la altura de la etiqueta:

extension UILabel {

    func heightForLabel(text:String, font:UIFont, width:CGFloat) -> CGFloat {
        let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
        label.font = font
        label.text = text

        label.sizeToFit()
        return label.frame.height
    }

}

1

Swift 5, XCode 11 forma de guión gráfico. Creo que esto funciona para iOS 9 y versiones posteriores. Si desea, por ejemplo, la etiqueta "Descripción" para obtener la altura dinámica, siga los pasos:

1) Seleccione la etiqueta de descripción -> Ir al Inspector de atributos (icono de lápiz), establezca: Líneas: 0 Salto de línea: Ajuste de palabras

2) Seleccione su UILabel del guión gráfico y vaya al Inspector de tamaño (icono de regla), 3) Vaya a "Prioridad de resistencia a la compresión de contenido a 1 para todos los demás componentes de UIView (etiquetas, botones, vista de imágenes, etc.) que interactúan con su etiqueta.

Por ejemplo, tengo UIImageView, Etiqueta de título y Etiqueta de descripción verticalmente en mi vista. Establecí la Prioridad de resistencia a la compresión de contenido en UIImageView y la etiqueta del título en 1 y la etiqueta de descripción en 750. Esto hará que una etiqueta de descripción tome la altura necesaria.


0

Para hacer que la etiqueta sea dinámica en Swift, no proporcione una constancia de altura y, en el guión gráfico, haga que el número de líneas de la etiqueta 0 también dé una restricción inferior y esta es la mejor manera de manejar la etiqueta dinámica según el tamaño de su contenido.


0

También puede utilizar la sizeThatFitsfunción.

Por ejemplo:

label.sizeThatFits(superView.frame.size).height

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.