Passen Sie die UILabel-Höhe an den Text an


112

Ich habe einige Beschriftungen, deren Höhe ich an den Text anpassen möchte. Dies ist der Code, den ich jetzt dafür geschrieben habe

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
}

BEARBEITEN:

Das Problem war nicht in diesem Code enthalten, daher liegt mein Fix in der Frage selbst. Es könnte immer noch für andere nützlich sein!


Werfen Sie einen Blick auf die NSString UIKit-Ergänzungen. Dort gibt es Methoden, um die benötigte Größe zu berechnen, ohne ein UILabel zu erstellen.
Vladimir Gritsenko

@VladimirGritsenko die 'sizeWithFont'-Methoden sind in Swift nicht verfügbar :(
TheBurgerShot

Ich gebe zu, dass ich kein Experte für Swift bin, aber ich glaube, Sie können Ihre eigenen Überbrückungsmethoden hinzufügen. Es würde sich immer noch lohnen, UILabel zu erstellen, um die Größe zu berechnen.
Vladimir Gritsenko

@TheBurgerShot ist sizeWithFontmöglicherweise nicht für Swift verfügbar, Stringaber es ist verfügbar für NSStringSie sollten es trotzdem aufrufen können.
Anorak

Am Ende war der Fehler etwas anderes und hatte nichts mit dieser Methode zu tun. Dies könnte jedoch für andere hilfreich sein.
TheBurgerShot

Antworten:


189

Ich habe das gerade auf einen Spielplatz gestellt und es funktioniert für mich.

Aktualisiert für 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
}

Geben Sie hier die Bildbeschreibung ein


Dies funktioniert auch für mich auf dem Spielplatz. Der Fehler scheint an dieser bestimmten Stelle nicht aufzutreten. Wenn ich die Verwendung dieser Methode entferne, wird es über einige Drucke oder nur eine Zeile mit nur Kommentaren jammern (dann heißt es EXC_BAD_ACCESS code = 2 auch)
TheBurgerShot

6
Es funktioniert auf einem Spielplatz, aber innerhalb eines View-Controllers in XCode 6.1
Unome

1
Ich zögere ein wenig, eine neue UILabelGröße zu erstellen . Wenn diese Methode im Inneren verwendet wird layoutSubviewsund die Tendenz besteht, mehrmals pro vollständigem Layout aufgerufen zu werden, kann die zusätzliche Objekterstellung zu merklichen Verzögerungen führen, insbesondere beim Scrollen.
Zorayr

let textRect = textString.boundingRectWithSize (CGSizeMake (320, 2000), Optionen: .UsesLineFragmentOrigin, Attribute: textAttributes, Kontext: nil)
Siddharth Pancholi

Ich kann diese Funktion in meinem View Controller nicht aufrufen ... Können Sie mir vorschlagen, was der mögliche Grund sein könnte?
Rouny

64

Wenn Sie AutoLayout verwenden , können Sie die UILabelHöhe nur über die Konfigurationsoberfläche anpassen .

Für iOS8 oder höher

  • Legen Sie die Einschränkung führend / nachlaufend für Ihre fest UILabel
  • Und ändern Sie die Zeilen UILabelvon 1 auf 0

Geben Sie hier die Bildbeschreibung ein

Für iOS7

  • Zuerst müssen Sie enthält enthält Höhe fürUILabel
  • Dann ändern Sie die Beziehung von EqualzuGreater than or Equal

Geben Sie hier die Bildbeschreibung ein

  • Schließlich ändern sich die Linien von UILabel1 bis 0

Geben Sie hier die Bildbeschreibung ein

Ihr UILabelWille automatisch erhöht Höhe je nach Text


2
Und wenn sich das Etikett in einer Zelle befindet. Wann und wie würden Sie die Zellenhöhe entsprechend erhöhen?
Oyalhi

1
@oyalhi, wenn sich Ihr Etikett in einer Zelle mit Tabellenansicht befindet, lesen
Phan Van Linh

3
Das hat bei mir perfekt funktioniert! Richten Sie die Einschränkungen ein und es wird richtig funktionieren!
Bill Thompson

2
funktioniert nicht für mich ... das Wort "Label" in einem UILabel macht height = 20. Es bleibt 20 nach dieser Einstellung.
Gadget00

9

Ich erstelle diese Erweiterung, wenn Sie möchten

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

8

Ich habe eine starke Arbeitslösung.

in layoutSubviews:

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

im Textsetzer:

    _title.text = newValue
    setNeedsLayout()

UPD. Natürlich mit diesen UILabel-Einstellungen:

    _title.lineBreakMode = .ByWordWrapping
    _title.numberOfLines = 0

6

Nur durch Einstellen:

label.numberOfLines = 0

Das Etikett passt seine Höhe automatisch an die eingegebene Textmenge an.


27
Dadurch kann das UILabel seine Höhe nicht anpassen.
TheBurgerShot

6

Basierend auf Anoraks Antwort stimme ich auch Zorayrs Besorgnis zu. Deshalb habe ich ein paar Zeilen hinzugefügt, um das UILabel zu entfernen und nur das CGFloat zurückzugeben. Ich weiß nicht, ob es hilft, da der ursprüngliche Code das UIabel nicht hinzufügt, aber es wirft keinen Fehler, daher verwende ich den folgenden Code:

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 und Xcode 9.4.1

Nur 3 Schritte

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

Schritt 2)

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

Schritt 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

Die von Anorak als berechnete Eigenschaft in einer Erweiterung für UILabel vorgeschlagene Lösung:

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

Verwendung:

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

Schöne Lösung! Vielen Dank :-)
Cristina

Eigenschaft kann nicht zugewiesen werden: 'height' ist eine Nur-Get-Eigenschaft.
Amg91

4

Nach der Antwort von @Anorak habe ich diese Erweiterung zu String hinzugefügt und einen Einschub als Parameter gesendet, da Sie häufig eine Auffüllung Ihres Textes benötigen. Wie auch immer, vielleicht finden Sie einige nützlich.

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 diese Zeile hat mir geholfen, danke.
Coder_A_D

3

Hier erfahren Sie, wie Sie die Texthöhe in Swift berechnen. Sie können dann die Höhe vom Rechteck abrufen und die Einschränkungshöhe des Etiketts oder der Textansicht usw. festlegen.

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

Rufen Sie einfach diese Methode auf, wenn Sie eine dynamische Höhe für die Beschriftung benötigen

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, Breite: UIScreen.main.bounds.width - 80, Höhe: 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 gilt für ganze Absätze, nicht für Wörter innerhalb von Absätzen. Diese Eigenschaft gilt sowohl beim normalen Zeichnen als auch in Fällen, in denen die Schriftgröße reduziert werden muss, damit sie in den Begrenzungsrahmen des Etiketts passt. Diese Eigenschaft ist standardmäßig auf byTruncatingTail festgelegt.

Dieser Link beschreibt die Storyboard-Methode, um dasselbe zu tun


2
Nur-Code-Antworten gelten nicht als bewährte Methode. Bitte fügen Sie einige Erklärungen hinzu, wie Ihre Antwort die Frage beantwortet.
Yannis

2

Swift 4.0

Anstatt die Text- / Beschriftungshöhe zu berechnen, ändere ich die Größe der Beschriftung nach dem Einfügen des (dynamischen) Textes.

Angenommen, myLabel ist das betreffende UILabel:

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

Und jetzt kommt der lustige Teil:

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

2

Die Swift 4.1- Erweiterungsmethode zur Berechnung der Etikettenhöhe:

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 Storyboard Weg. Ich denke, das funktioniert für iOS 9 und höher. Führen Sie die folgenden Schritte aus, damit beispielsweise die Bezeichnung "Beschreibung" die dynamische Höhe erhält:

1) Beschreibungsbeschriftung auswählen -> Zum Attributinspektor (Stiftsymbol) gehen und Folgendes festlegen: Zeilen: 0 Zeilenumbruch: Zeilenumbruch

2) Wählen Sie Ihr UILabel aus dem Storyboard aus und gehen Sie zum Größeninspektor (Linealsymbol). 3) Gehen Sie für alle anderen UIView-Komponenten (Etiketten, Schaltflächen, Bildansicht usw.), die mit Ihrem Etikett interagieren, zu "Priorität für Inhaltskomprimierungswiderstand 1".

Zum Beispiel habe ich UIImageView, Title Label und Description Label vertikal in meiner Ansicht. Ich habe die Prioritätspriorität für die Inhaltskomprimierung auf UIImageView und die Titelbezeichnung auf 1 und für die Beschreibungsbezeichnung auf 750 festgelegt. Dadurch wird eine Beschreibungsbezeichnung so erstellt, dass sie die erforderliche Höhe annimmt.


0

Um das Etikett schnell dynamisch zu machen, geben Sie keine Höhenbeschränkung an und geben Sie im Storyboard die Anzahl der Zeilen 0 für das Etikett an. Dies ist die beste Art und Weise, wie ich dynamisches Etikett gemäß seiner Inhaltsgröße handhabe.


0

Sie können auch die sizeThatFitsFunktion verwenden.

Beispielsweise:

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.