Polsterung einer UILabel
vollständigen Lösung. Aktualisiert für 2020.
Es stellt sich heraus, dass drei Dinge getan werden müssen.
1. Muss textRect # forBounds mit der neuen kleineren Größe aufrufen
2. Muss drawText mit der neuen kleineren Größe überschreiben
3. Wenn es sich um eine Zelle mit dynamischer Größe handelt, muss intrinsicContentSize angepasst werden
Im folgenden typischen Beispiel befindet sich die Texteinheit in einer Tabellenansicht, Stapelansicht oder einer ähnlichen Konstruktion, wodurch sie eine feste Breite erhält . Im Beispiel wollen wir eine Polsterung von 60,20,20,24.
Daher nehmen wir die "vorhandene" intrinsicContentSize und addieren tatsächlich 80 zur Höhe .
Wiederholen ...
Sie müssen buchstäblich die vom Motor "bisher" berechnete Höhe "erhalten" und diesen Wert ändern .
Ich finde diesen Prozess verwirrend, aber so funktioniert es. Für mich sollte Apple einen Anruf mit dem Namen "vorläufige Höhenberechnung" veröffentlichen.
Zweitens müssen wir den Aufruf textRect # forBounds mit unserer neuen kleineren Größe verwenden .
In textRect # forBounds verkleinern wir zuerst die Größe und dann rufen super auf.
Aufmerksam! Sie müssen super danach anrufen , nicht vorher !
Wenn Sie alle Versuche und Diskussionen auf dieser Seite sorgfältig untersuchen, ist dies genau das Problem. Beachten Sie, dass einige Lösungen "fast zu funktionieren scheinen", aber dann wird jemand berichten, dass es in bestimmten Situationen nicht funktioniert. Dies ist in der Tat der genaue Grund - verwirrenderweise müssen Sie "super danach anrufen", nicht vorher.
Wenn Sie es also "in der falschen Reihenfolge" super nennen, funktioniert es normalerweise, aber nicht für bestimmte Textlängen .
Hier ist ein genaues visuelles Beispiel für "falsches Super zuerst machen":
Beachten Sie, dass die Ränder 60,20,20,24 korrekt sind, ABER die Größenberechnung ist tatsächlich falsch, da sie mit dem Muster "super first" in textRect # forBounds durchgeführt wurde.
Fest:
Beachten Sie, dass die textRect # forBounds-Engine erst jetzt weiß, wie die Berechnung ordnungsgemäß durchgeführt wird :
Schließlich!
Auch in diesem Beispiel wird das UILabel in der typischen Situation verwendet, in der die Breite festgelegt ist. In intrinsicContentSize müssen wir also die gewünschte zusätzliche Gesamthöhe "hinzufügen". (Sie müssen die Breite in keiner Weise "hinzufügen", das wäre bedeutungslos, da es feststeht.)
Dann erhalten Sie in textRect # forBounds die "bisher vorgeschlagenen" Grenzen durch Autolayout, subtrahieren Ihre Ränder und rufen erst dann erneut die textRect # forBounds-Engine auf, dh in super, wodurch Sie ein Ergebnis erhalten.
Schließlich und einfach in drawText zeichnen Sie natürlich in derselben kleineren Box.
Puh!
let UIEI = UIEdgeInsets(top: 60, left: 20, bottom: 20, right: 24) // as desired
override var intrinsicContentSize:CGSize {
numberOfLines = 0 // don't forget!
var s = super.intrinsicContentSize
s.height = s.height + UIEI.top + UIEI.bottom
s.width = s.width + UIEI.left + UIEI.right
return s
}
override func drawText(in rect:CGRect) {
let r = rect.inset(by: UIEI)
super.drawText(in: r)
}
override func textRect(forBounds bounds:CGRect,
limitedToNumberOfLines n:Int) -> CGRect {
let b = bounds
let tr = b.inset(by: UIEI)
let ctr = super.textRect(forBounds: tr, limitedToNumberOfLines: 0)
// that line of code MUST be LAST in this function, NOT first
return ctr
}
Noch einmal. Beachten Sie, dass die Antworten auf diese und andere Fragen, die "fast" richtig sind, das Problem im ersten Bild oben haben - das "Super ist am falschen Ort" . Sie müssen die Größe in intrinsicContentSize erhöhen und dann in textRect # forBounds zuerst die Grenzen des ersten Vorschlags verkleinern und dann super aufrufen.
Zusammenfassung: Sie müssen in textRect # forBounds "super last " aufrufen
Das ist das Geheimnis.
Beachten Sie, dass Sie nicht zusätzlich invalidate, sizeThatFits, needLayout oder einen anderen erzwungenen Aufruf aufrufen müssen und sollten. Eine korrekte Lösung sollte im normalen Autolayout-Ziehzyklus ordnungsgemäß funktionieren.
Trinkgeld:
Wenn Sie mit Monospace-Schriftarten arbeiten, finden Sie hier einen guten Tipp: https://stackoverflow.com/a/59813420/294884