Ich kopiere dieselbe Frage vor Frage . Ich habe die angegebenen Lösungen ausprobiert und konnte sie nicht lösen, da sizetofit bei Verwendung von Autolayout nicht wirksam war.
Die erwartete Anzeige ist wie folgt.
Bearbeiten
In meiner ursprünglichen Antwort habe ich den Absatzstil des Labels verwendet. Es stellt sich heraus, dass bei mehrzeiligen Etiketten tatsächlich verhindert wird, dass das Etikett mehrzeilig ist. Als Ergebnis habe ich es aus der Berechnung entfernt. Mehr dazu in Github
Für diejenigen, die sich mit Open Source besser auskennen, schauen Sie auf jeden Fall nach TTTAttributedLabel , wo Sie die Textausrichtung des Labels auf TTTAttributedLabelVerticalAlignmentTop
setzen können.
Der Trick ist die Unterklasse UILabel
und die Überschreibung von drawTextInRect
. Erzwingen Sie dann, dass der Text am Ursprung der Grenzen des Etiketts gezeichnet wird.
Hier ist eine naive Implementierung, die Sie jetzt verwenden können:
@IBDesignable class TopAlignedLabel: UILabel {
override func drawTextInRect(rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
var labelStringSize = stringTextAsNSString.boundingRectWithSize(CGSizeMake(CGRectGetWidth(self.frame), CGFloat.max),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
super.drawTextInRect(CGRectMake(0, 0, CGRectGetWidth(self.frame), ceil(labelStringSize.height)))
} else {
super.drawTextInRect(rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.blackColor().CGColor
}
}
@IBDesignable class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width,height: CGFloat.greatestFiniteMagnitude),
options: NSStringDrawingOptions.usesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
super.drawText(in: CGRect(x:0,y: 0,width: self.frame.width, height:ceil(labelStringSize.height)))
} else {
super.drawText(in: rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.black.cgColor
}
}
IB_DESIGNABLE
@interface TopAlignedLabel : UILabel
@end
@implementation TopAlignedLabel
- (void)drawTextInRect:(CGRect)rect {
if (self.text) {
CGSize labelStringSize = [self.text boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.frame), CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:@{NSFontAttributeName:self.font}
context:nil].size;
[super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),ceilf(labelStringSize.height))];
} else {
[super drawTextInRect:rect];
}
}
- (void)prepareForInterfaceBuilder {
[super prepareForInterfaceBuilder];
self.layer.borderWidth = 1;
self.layer.borderColor = [UIColor blackColor].CGColor;
}
@end
Da ich IBDesignable verwendet habe, können Sie dieses Label zu einem Storyboard hinzufügen und sehen, wie es läuft. So sieht es für mich aus
Wenn Sie nicht durch UILabel mit fester Größe eingeschränkt sind, verwenden Sie , anstatt den Text innerhalb eines UILabels auszurichten, einfach die Einschränkung ≥ für das angegebene Label, um die Größe des Labels zu ändern.
Es ist die eleganteste Lösung mit Auto Layout. Vergessen Sie nicht, numberOfLines auf Null zu setzen.
Sie können UITextView anstelle von UILabel verwenden:
Deaktivieren Sie "Scrollen aktiviert".
Deaktivieren Sie "Bearbeitbar".
Deaktivieren Sie "Auswählbar".
Hintergrundfarbe auf ClearColor setzen
Stattdessen habe ich die untere Raumkonstante auf Priorität @ 250 geändert und mein Problem gelöst. Und mein Etikett hat konstant eine konstante Höhe
Sie würden das tun, indem Sie die minimale Höhe entfernen.
Wenn Sie die Mindesthöhe für etwas anderes unterhalb des Etiketts benötigen, verwenden Sie eine Containeransicht, deren Größe basierend auf dem Etiketteninhalt angepasst, jedoch ein Minimum verwendet wird.
Ich habe die Lösung von @Daniel Golasko verwendet. Immer wenn der Text im UILabel länger war als das UILabel enthalten konnte, bewegte sich der Text nach unten, anstatt an der Spitze ausgerichtet zu bleiben.
Ich habe diese Zeile geändert, um sicherzustellen, dass der Text richtig ausgerichtet ist
[super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),MIN(ceilf(labelStringSize.height), self.frame.size.height))];
Sie sollten UILabel als Unterklasse definieren und die Wiedergabe von Textanzeigen überschreiben.
class UITopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
guard let string = text else {
super.drawText(in: rect)
return
}
let size = (string as NSString).boundingRect(
with: CGSize(width: rect.width, height: .greatestFiniteMagnitude),
options: [.usesLineFragmentOrigin],
attributes: [.font: font],
context: nil).size
var rect = rect
rect.size.height = size.height.rounded()
super.drawText(in: rect)
}
}
Ich hatte ein ähnliches Problem, bei dem es 3 Labels gab. Das mittlere Etikett könnte einen viel längeren Text haben als die anderen beiden, sodass seine Höhe viel größer werden könnte.
So was:
Ich habe die Einschränkung für den unteren Abstand des mittleren Labels auf> = das untere Label gesetzt.
Das hat mein Problem gelöst.
Auto-Layout funktioniert nur mit Kanten/Größen des Controllers, nicht mit Controller-Inhalten. Daher ist es keine gute Idee, das Auto-Layout zu verwenden, um Ihren Beschriftungstext über der ersten Zeile anzuzeigen so.
@IBInspectable var alignTop: Bool = false
func setAlignTop() {
let text = self.text!
let lines = text.characters.split(separator: "\n").count
if lines < self.numberOfLines {
var newLines = ""
for _ in 0..<(self.numberOfLines - lines) {
newLines = newLines.appending("\n ")
}
self.text! = text.appending(newLines)
}
}
override var text: String? {
didSet {
if alignTop {
self.setAlignTop()
}
}
}
Sie können versuchen, wenn die Schaltfläche [button setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
Bearbeiten:
Sie können dies versuchen, wenn Sie nur das Etikett verwenden möchten:
use dies ist meine Klasse, Sie können den Text alignment
durch contentMode
ändern.
unterstützter Fall: .top, .bottom, .left, .right, .topLeft, .topRight, .bottomLeft, .bottomRight
Swift4
import Foundation
import UIKit
@IBDesignable
class UIAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let text = text as NSString? {
func defaultRect(for maxSize: CGSize) -> CGRect {
let size = text
.boundingRect(
with: maxSize,
options: NSStringDrawingOptions.usesLineFragmentOrigin,
attributes: [
NSAttributedStringKey.font: font
],
context: nil
).size
let rect = CGRect(
Origin: .zero,
size: CGSize(
width: min(frame.width, ceil(size.width)),
height: min(frame.height, ceil(size.height))
)
)
return rect
}
switch contentMode {
case .top, .bottom, .left, .right, .topLeft, .topRight, .bottomLeft, .bottomRight:
let maxSize = CGSize(width: frame.width, height: frame.height)
var rect = defaultRect(for: maxSize)
switch contentMode {
case .bottom, .bottomLeft, .bottomRight:
rect.Origin.y = frame.height - rect.height
default: break
}
switch contentMode {
case .right, .topRight, .bottomRight:
rect.Origin.x = frame.width - rect.width
default: break
}
super.drawText(in: rect)
default:
super.drawText(in: rect)
}
} else {
super.drawText(in: rect)
}
}
}
Hier ist eine Verbesserung der Swift 3-Lösung von Daniel Galasko (hier können Sie auch die maximale Zeilennummer ohne Versatz oben einstellen):
import UIKit
@IBDesignable class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
let labelString = stringTextAsNSString.boundingRect(with: CGSize(width: frame.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
super.drawText(in: CGRect(x: 0, y: 0, width: frame.width, height: ceil(labelString.size.height) > frame.height ? frame.height : ceil(labelString.size.height)))
} else {
super.drawText(in: rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.black.cgColor
}
}
Für mich habe ich die Höhenbeschränkung nicht festgelegt, der Text wächst immer vom oberen Rand der Beschriftung aus .. Die Einschränkungen für diese Beschriftung sind oben, links und rechts Zahlen, also keine Sorgen über die Höhe.