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!

TheBurgerShot
quelle
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

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

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

Nur durch Einstellen:

label.numberOfLines = 0

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

Jordan Amman
quelle
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
}
LeftyT
quelle
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)
iOS
quelle
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
Philipp Otto
quelle
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
    }
}
Lirik
quelle
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)
Collin
quelle
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
}
Shubham Bairagi
quelle
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

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

}

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

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

Ranjeet Raushan
quelle
0

Sie können auch die sizeThatFitsFunktion verwenden.

Beispielsweise:

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

Fitsyu
quelle