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!

TheBurgerShot
fuente
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í

Anorak
fuente
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

Phan Van Linh
fuente
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()
    }
}
YannSteph
fuente
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
dimpiax
fuente
6

Solo configurando:

label.numberOfLines = 0

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

Jordania Amman
fuente
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
}
LeftyT
fuente
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)
iOS
fuente
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
Philipp Otto
fuente
¡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
    }
}
Lirik
fuente
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)
Collin
fuente
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
}
Shubham bairagi
fuente
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

7ur7l3
fuente
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()
   }
}
Patrick J.
fuente
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
    }

}

fuente
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.

Doci
fuente
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.

Ranjeet Raushan
fuente
0

También puede utilizar la sizeThatFitsfunción.

Por ejemplo:

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

Fitsyu
fuente