Regola l'altezza dell'etichetta UIL sul testo


112

Ho alcune etichette di cui voglio adattare l'altezza al testo, questo è il codice che ho scritto per questo ora

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
}

MODIFICARE:

Il problema non era in questo pezzo di codice, quindi la mia soluzione è nella domanda stessa. Potrebbe ancora essere utile per gli altri!


Dai un'occhiata alle aggiunte di NSString UIKit, ci sono metodi per calcolare le dimensioni di cui hai bisogno senza creare un UILabel.
Vladimir Gritsenko

@VladimirGritsenko i metodi 'sizeWithFont' non sono disponibili in Swift :(
TheBurgerShot

Ammetto di non essere un esperto di Swift, ma credo che tu possa aggiungere i tuoi metodi di bridging. Varrebbe comunque la pena creare UILabel per calcolare le dimensioni.
Vladimir Gritsenko

@TheBurgerShot sizeWithFontpotrebbe non essere disponibile per Swift Stringma è disponibile su NSStringDovresti comunque essere in grado di richiamarlo.
Anorak

Alla fine, l'errore era qualcosa di diverso e non aveva nulla a che fare con questo metodo. Anche se questo potrebbe ancora essere utile per gli altri.
TheBurgerShot

Risposte:


189

L'ho appena messo in un parco giochi e per me funziona.

Aggiornato per 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
}

inserisci qui la descrizione dell'immagine


questo funziona bene anche per me nel playground, l'errore non sembra verificarsi in questo posto specifico, quando rimuovo gli usi di questo metodo si lamenterà di alcune stampe o solo di una riga con solo commenti (quindi dice EXC_BAD_ACCESS code = 2)
TheBurgerShot

6
Funziona in un parco giochi, ma nessun dimensionamento si verifica come desiderato all'interno di un controller di visualizzazione in XCode 6.1
Unome

1
Sono un po 'titubante nel creare un nuovo UILabelper dimensionamento; se questo metodo viene utilizzato all'interno layoutSubviewscon la tendenza ad essere invocato più volte per layout completo, la creazione di oggetti extra può introdurre notevoli ritardi, specialmente durante lo scorrimento.
Zorayr

let textRect = textString.boundingRectWithSize (CGSizeMake (320, 2000), opzioni: .UsesLineFragmentOrigin, attributi: textAttributes, context: nil)
Siddharth Pancholi

Non riesco a chiamare questa funzione nel mio controller di visualizzazione ... Potete suggerirmi quale potrebbe essere la possibile ragione?
Rouny

64

Se stai utilizzando AutoLayout , puoi regolare l' UILabelaltezza solo tramite l'interfaccia utente di configurazione.

Per iOS8 o versioni successive

  • Imposta il vincolo iniziale / finale per il tuo UILabel
  • E cambia le linee UILabelda 1 a 0

inserisci qui la descrizione dell'immagine

Per iOS7

  • Innanzitutto , è necessario aggiungere contiene l'altezza perUILabel
  • Quindi , modificare la relazione da EqualaGreater than or Equal

inserisci qui la descrizione dell'immagine

  • Infine , cambia le righe UILabelda 1 a 0

inserisci qui la descrizione dell'immagine

Il tuo UILabelaumenterà automaticamente l'altezza a seconda del testo


2
E se l'etichetta è all'interno di una cella. Quando e come aumenteresti l'altezza della cella di conseguenza?
oyalhi

1
@oyalhi, se la tua etichetta è all'interno di una cella tableview, consulta il mio altro post stackoverflow.com/a/36277840/5381331
Phan Van Linh

3
Ha funzionato perfettamente per me! Imposta i vincoli e funzionerà correttamente!
Bill Thompson

2
non funziona per me ... la parola "Etichetta" in una UILabel rende height = 20. Rimane 20 dopo questa impostazione.
gadget00

9

Creo questa estensione se vuoi

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

8

Ho una soluzione di lavoro forte.

in layoutSottoviste:

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

nel setter di testo:

    _title.text = newValue
    setNeedsLayout()

UPD. ovviamente con queste impostazioni UILabel:

    _title.lineBreakMode = .ByWordWrapping
    _title.numberOfLines = 0

6

Semplicemente impostando:

label.numberOfLines = 0

L'etichetta regola automaticamente la sua altezza in base alla quantità di testo immessa.


27
Questo non obbliga l'UILabel a regolare la sua altezza.
TheBurgerShot

6

sulla base della risposta di Anorak, sono anche d'accordo con la preoccupazione di Zorayr, quindi ho aggiunto un paio di righe per rimuovere UILabel e restituire solo CGFloat, non so se aiuta poiché il codice originale non aggiunge l'UIabel, ma non genera errori, quindi sto usando il codice seguente:

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

In swift 4.1 e Xcode 9.4.1

Solo 3 passaggi

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

Passo 2)

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

Passaggio 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 soluzione suggerita da Anorak come proprietà calcolata in un'estensione per 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

Bella soluzione! Grazie :-)
Cristina

Impossibile assegnare alla proprietà: "height" è una proprietà di sola ricezione.
Amg91

4

Seguendo la risposta di @Anorak, ho aggiunto questa estensione a String e ho inviato un riquadro come parametro, perché molte volte avrai bisogno di un riempimento al tuo testo. Ad ogni modo, forse alcuni lo troverai utile.

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 questa riga mi ha aiutato grazie.
Coder_A_D

3

Ecco come calcolare l'altezza del testo in Swift. È quindi possibile ottenere l'altezza dal rect e impostare l'altezza del vincolo dell'etichetta o textView, ecc.

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

basta chiamare questo metodo dove è necessaria l'altezza dinamica per l'etichetta

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 (frame: CGRect (x: 70, y: 60, larghezza: UIScreen.main.bounds.width - 80, altezza: 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, si applica a interi paragrafi, non alle parole all'interno dei paragrafi. Questa proprietà è attiva sia durante il normale disegno che nei casi in cui la dimensione del carattere deve essere ridotta per adattare il testo dell'etichetta nel suo riquadro di delimitazione. Questa proprietà è impostata su byTruncatingTail per impostazione predefinita.

Questo collegamento descrive il modo dello storyboard di fare lo stesso


2
Le risposte di solo codice non sono considerate buone pratiche. Considera l'idea di aggiungere alcune spiegazioni su come la tua risposta risponde alla domanda.
Yannis

2

Swift 4.0

Invece di calcolare l'altezza del testo / etichetta, ridimensiono semplicemente l'etichetta dopo aver inserito il testo (dinamico).

Supponendo che myLabel sia l'UILabel in questione:

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

E ora arriva la parte divertente:

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

2

Il metodo di estensione Swift 4.1 per calcolare l'altezza dell'etichetta:

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, modalità storyboard per XCode 11. Penso che funzioni per iOS 9 e versioni successive. Ad esempio, vuoi che l'etichetta "Descrizione" ottenga l'altezza dinamica, segui i passaggi:

1) Seleziona l'etichetta della descrizione -> Vai a Attributes Inspector (icona della matita), imposta: Linee: 0 Interruzione di riga: A capo automatico

2) Seleziona la tua UILabel dallo storyboard e vai a Size Inspector (icona del righello), 3) Vai in basso a "Content Compression Resistance Priority su 1 per tutti gli altri componenti UIView (etichette, pulsanti, visualizzazione immagine, ecc.) Che interagiscono con la tua etichetta.

Ad esempio, ho UIImageView, Etichetta titolo e Etichetta descrizione verticalmente nella mia vista. Ho impostato Content Compression Resistance Priority su UIImageView e l'etichetta del titolo su 1 e per l'etichetta di descrizione su 750. Questo farà sì che un'etichetta di descrizione prenda l'altezza necessaria.


0

Per rendere l'etichetta dinamica in modo rapido, non dare la costanza di altezza e nello storyboard fare in modo che il numero di righe dell'etichetta 0 dia anche un vincolo di fondo e questo è il modo migliore in cui gestisco l'etichetta dinamica in base alla dimensione del contenuto.


0

Puoi anche usare sizeThatFitsfunction.

Per esempio:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.