Ich habe ein "UILabel" mit Platz für zwei Textzeilen. Manchmal, wenn der Text zu kurz ist, wird dieser Text in der vertikalen Mitte des Etiketts angezeigt.
Wie kann ich den Text vertikal so ausrichten, dass er sich immer am oberen Rand des "UILabel" befindet?
Es gibt keine Möglichkeit, die vertikale Ausrichtung bei einem "UILabel" einzustellen, aber Sie können den gleichen Effekt erzielen, indem Sie den Rahmen des Labels ändern. Ich habe meine Etiketten orange gefärbt, damit Sie deutlich sehen können, was passiert.
Hier ist der schnelle und einfache Weg, dies zu tun:
[myLabel sizeToFit];
Wenn Sie ein Etikett mit längerem Text haben, das mehr als eine Zeile benötigt, setzen Sie numberOfLines
auf 0
(Null bedeutet hier eine unbegrenzte Anzahl von Zeilen).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Längere Version
Ich werde mein Etikett im Code erstellen, damit Sie sehen können, was vor sich geht. Sie können das meiste davon auch im Interface Builder einrichten. Bei meinem Setup handelt es sich um eine ansichtsbasierte App mit einem Hintergrundbild, das ich in Photoshop erstellt habe, um die Ränder zu zeigen (20 Punkte). Das Etikett hat eine attraktive orange Farbe, damit Sie sehen können, was mit den Abmessungen passiert.
- (void)viewDidLoad
{
[super viewDidLoad];
// 20 point top and left margin. Sized to leave 20 pt at right.
CGRect labelFrame = CGRectMake(20, 20, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setBackgroundColor:[UIColor orangeColor]];
NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
[myLabel setText:labelText];
// Tell the label to use an unlimited number of lines
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
[self.view addSubview:myLabel];
}
Einige Einschränkungen bei der Verwendung von sizeToFit
kommen ins Spiel, wenn der Text mittig oder rechts ausgerichtet ist. Das passiert folgendermaßen:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
Das Etikett hat immer noch eine feste Größe und eine feste linke obere Ecke. Sie können die ursprüngliche Breite des Etiketts in einer Variablen speichern und diese nach sizeToFit
setzen oder eine feste Breite angeben, um diesen Problemen zu begegnen:
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
CGRect myFrame = myLabel.frame;
// Resize the frame's width to 280 (320 - margins)
// width could also be myOriginalLabelFrame.size.width
myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
myLabel.frame = myFrame;
Beachten Sie, dass sizeToFit
die Mindestbreite Ihres ursprünglichen Etiketts respektiert. Wenn Sie mit einem 100 breiten Etikett beginnen und sizeToFit
aufrufen, erhalten Sie ein (möglicherweise sehr hohes) Etikett mit 100 (oder etwas weniger) Breite zurück. Sie sollten Ihr Etikett auf die gewünschte Mindestbreite einstellen, bevor Sie die Größe ändern.
Korrektur der Etikettenausrichtung durch Größenänderung der Rahmenbreite]5
Einige andere Dinge sind zu beachten:
Ob lineBreakMode
beachtet wird, hängt davon ab, wie er eingestellt ist. NSLineBreakByTruncatingTail
(die Voreinstellung) wird nach sizeToFit
ignoriert, ebenso wie die beiden anderen Abschneidemodi (Kopf und Mitte). Auch NSLineBreakByClipping
wird ignoriert. NSLineBreakByCharWrapping" funktioniert wie üblich. Die Rahmenbreite wird nach wie vor so verringert, dass sie auf den ganz rechten Buchstaben passt.
Mark Amery gab in den Kommentaren eine Lösung für NIBs und Storyboards mit Auto-Layout an:
Wenn Ihr Label in einer NIB oder einem Storyboard als Unteransicht der
View
eines ViewControllers enthalten ist, der Autolayout verwendet, dann wird der Aufruf vonsizeToFit
inviewDidLoad
nicht funktionieren, weil Autolayout die Größe und Position der Unteransichten nach dem Aufruf vonviewDidLoad
bestimmt und die Auswirkungen des Aufrufs vonsizeToFit
sofort rückgängig macht. Der Aufruf vonsizeToFit
innerhalb vonviewDidLayoutSubviews
wird jedoch funktionieren.
Dies verwendet die NSString
-Methode sizeWithFont:constrainedToSize:lineBreakMode:
, um die Rahmenhöhe zu berechnen, die benötigt wird, um einen String einzupassen, und setzt dann den Ursprung und die Breite.
Ändern Sie die Größe des Rahmens für das Etikett mit dem Text, den Sie einfügen möchten. Auf diese Weise können Sie eine beliebige Anzahl von Zeilen unterbringen.
CGSize maximumSize = CGSizeMake(300, 9999);
NSString *dateString = @"The date today is January 1st, 1999";
UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [dateString sizeWithFont:dateFont
constrainedToSize:maximumSize
lineBreakMode:self.dateLabel.lineBreakMode];
CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);
self.dateLabel.frame = dateFrame;
Wie die Antwort oben, aber es war nicht ganz richtig, oder einfach in Code zu klatschen, so dass ich es ein wenig bereinigt. Fügen Sie diese Erweiterung entweder in eine eigene .h- und .m-Datei ein oder fügen Sie sie einfach direkt über der Implementierung ein, die Sie verwenden möchten:
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end
@implementation UILabel (VerticalAlign)
- (void)alignTop
{
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<= newLinesToPad; i++)
{
self.text = [self.text stringByAppendingString:@" \n"];
}
}
- (void)alignBottom
{
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i< newLinesToPad; i++)
{
self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
}
@end
Um sie dann zu verwenden, fügen Sie Ihren Text in das Label ein und rufen dann die entsprechende Methode auf, um ihn auszurichten:
[myLabel alignTop];
oder
[myLabel alignBottom];
Ich habe eine Weile gebraucht, um den Code sowie den Code auf der eingeführten Seite zu lesen, und habe festgestellt, dass sie alle versuchen, die Rahmengröße des Etiketts zu ändern, so dass die standardmäßige vertikale Ausrichtung in der Mitte nicht angezeigt wird.
In einigen Fällen möchten wir jedoch, dass die Beschriftung alle diese Bereiche einnimmt, auch wenn die Beschriftung so viel Text hat (z. B. mehrere Zeilen mit gleicher Höhe).
Hier habe ich eine alternative Lösung gefunden, indem ich einfach Zeilenumbrüche am Ende der Beschriftung eingefügt habe (bitte beachten Sie, dass ich das UILabel
geerbt habe, aber es ist nicht notwendig):
CGSize fontSize = [self.text sizeWithFont:self.font];
finalHeight = fontSize.height * self.numberOfLines;
finalWidth = size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i = 0; i < newLinesToPad; i++)
{
self.text = [self.text stringByAppendingString:@"\n "];
}