Ho una UILabel
con spazio per due righe di testo. A volte, quando il testo è troppo corto, questo testo viene visualizzato nel centro verticale dell'etichetta.
Come posso allineare verticalmente il testo in modo che sia sempre in cima alla UILabel
?
Non c'è modo di impostare l'allineamento verticale su una UILabel
, ma puoi ottenere lo stesso effetto cambiando la cornice dell'etichetta. Ho reso le mie etichette arancioni in modo da poter vedere chiaramente cosa sta succedendo.
Ecco il modo semplice e veloce per farlo:
[myLabel sizeToFit];
Se hai un'etichetta con un testo più lungo che farà più di una linea, imposta numberOfLines
a 0
(zero qui significa un numero illimitato di linee).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Versione più lunga
Farò la mia etichetta in codice in modo che possiate vedere cosa sta succedendo. È possibile impostare la maggior parte di questo in Interface Builder troppo. La mia configurazione è una View-Based App con un'immagine di sfondo che ho fatto in Photoshop per mostrare i margini (20 punti). L'etichetta è di un attraente colore arancione in modo da poter vedere cosa sta succedendo con le dimensioni.
- (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];
}
Alcune limitazioni dell'uso di sizeToFit
entrano in gioco con testo allineato al centro o a destra. Ecco cosa succede:
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
L'etichetta è ancora dimensionata con un angolo fisso in alto a sinistra. Potete salvare la larghezza dell'etichetta originale in una variabile e impostarla dopo sizeToFit
, o darle una larghezza fissa per contrastare questi problemi:
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;
Notate che sizeToFit
rispetterà la larghezza minima della vostra etichetta iniziale. Se iniziate con un'etichetta larga 100 e chiamate sizeToFit
su di essa, vi restituirà un'etichetta (possibilmente molto alta) con larghezza 100 (o poco meno). Potresti voler impostare la tua etichetta alla larghezza minima che vuoi prima di ridimensionarla.
Correggere l'allineamento dell'etichetta ridimensionando la larghezza del frame]5
Alcune altre cose da notare:
Il rispetto di lineBreakMode
dipende da come è impostato. NSLineBreakByTruncatingTail
(il default) è ignorato dopo sizeToFit
, così come le altre due modalità di troncamento (testa e centro). Anche NSLineBreakByClipping
è ignorato. NSLineBreakByCharWrapping
funziona come al solito. La larghezza della cornice è ancora ridotta per adattarsi alla lettera più a destra.
hr>
Mark Amery ha dato una correzione per NIB e Storyboard usando Auto Layout nei commenti:
Se la vostra etichetta è inclusa in un nib o in uno storyboard come sottoview della view
di un ViewController che usa l'autolayout, allora mettere la vostra chiamata sizeToFit
in viewDidLoad
non funzionerà, perché l'autolayout dimensiona e posiziona le sottoview dopo che viewDidLoad
è chiamato e annullerà immediatamente gli effetti della vostra chiamata sizeToFit
. Tuttavia, chiamare sizeToFit
dall'interno di viewDidLayoutSubviews
funzionerà.
hr> La mia risposta originale (per posterità/riferimento):
Questo usa il metodo NSString
sizeWithFont:constrainedToSize:lineBreakMode:
per calcolare l'altezza del frame necessaria per adattarsi a una stringa, quindi imposta l'origine e la larghezza.
Ridimensiona il frame per l'etichetta usando il testo che vuoi inserire. In questo modo puoi adattare qualsiasi numero di linee.
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;
Come la risposta sopra, ma non era del tutto giusto, o facile da schiaffare nel codice, così l'ho pulito un po'. Aggiungete questa estensione al suo proprio file .h e .m o semplicemente incollatela sopra l'implementazione che intendete usare:
#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
E poi per usarla, mettete il vostro testo nell'etichetta, e poi chiamate il metodo appropriato per allinearlo:
[myLabel alignTop];
o
[myLabel alignBottom];
Mi sono preso un po' di tempo per leggere il codice, così come il codice nella pagina introduttiva, e ho scoperto che tutti cercano di modificare la dimensione della cornice dell'etichetta, in modo che l'allineamento verticale centrale predefinito non appaia.
Tuttavia, in alcuni casi vogliamo che l'etichetta occupi tutti quegli spazi, anche se l'etichetta ha tanto testo (per esempio, più righe con la stessa altezza).
Qui, ho usato un modo alternativo per risolverlo, semplicemente riempiendo le newline alla fine dell'etichetta (si noti che in realtà ho ereditato la UILabel
, ma non è necessario):
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 "];
}