J'ai un UILabel
avec un espace pour deux lignes de texte. Parfois, lorsque le texte est trop court, il s'affiche au centre vertical de l'étiquette.
Comment aligner verticalement mon texte pour qu'il soit toujours en haut de l'écran ? UILabel
?
J'ai un UILabel
avec un espace pour deux lignes de texte. Parfois, lorsque le texte est trop court, il s'affiche au centre vertical de l'étiquette.
Comment aligner verticalement mon texte pour qu'il soit toujours en haut de l'écran ? UILabel
?
Il n'y a aucun moyen de définir l'alignement vertical d'un fichier UILabel
mais vous pouvez obtenir le même effet en modifiant le cadre de l'étiquette. J'ai mis mes étiquettes en orange pour que vous puissiez voir clairement ce qui se passe.
Voici la façon simple et rapide de le faire :
[myLabel sizeToFit];
Si vous avez une étiquette avec un texte plus long qui fera plus d'une ligne, définissez numberOfLines
à 0
(zéro signifie ici un nombre illimité de lignes).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Version plus longue
Je vais faire mon étiquette en code pour que vous puissiez voir ce qui se passe. Vous pouvez également configurer la plupart de ces éléments dans Interface Builder. Ma configuration est une application basée sur la vue avec une image de fond que j'ai créée dans Photoshop pour montrer les marges (20 points). L'étiquette est d'une couleur orange attrayante pour que vous puissiez voir ce qui se passe avec les dimensions.
- (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];
}
Certaines limites de l'utilisation sizeToFit
entrent en jeu avec un texte aligné au centre ou à droite. Voici ce qui se passe :
// myLabel.textAlignment = NSTextAlignmentRight;
myLabel.textAlignment = NSTextAlignmentCenter;
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
L'étiquette est toujours dimensionnée avec un coin supérieur gauche fixe. Vous pouvez sauvegarder la largeur de l'étiquette originale dans une variable et la définir après l'opération sizeToFit
ou lui donner une largeur fixe pour contrer ces problèmes :
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;
Notez que sizeToFit
respectera la largeur minimale de votre étiquette initiale. Si vous commencez avec une étiquette de 100 de large et que vous appelez sizeToFit
sur celle-ci, vous obtiendrez une étiquette (éventuellement très haute) de 100 (ou un peu moins) de largeur. Vous pourriez vouloir régler votre étiquette sur la largeur minimale souhaitée avant de la redimensionner.
Quelques autres choses à noter :
Si lineBreakMode
est respectée dépend de la façon dont elle est définie. NSLineBreakByTruncatingTail
(la valeur par défaut) est ignorée après sizeToFit
comme les deux autres modes de troncature (tête et milieu). NSLineBreakByClipping
est également ignorée. NSLineBreakByCharWrapping
fonctionne comme d'habitude. La largeur du cadre est toujours réduite pour s'adapter à la lettre la plus à droite.
Mark Amery a donné un correctif pour les NIBs et Storyboards utilisant la mise en page automatique dans les commentaires :
Si votre étiquette est incluse dans une nib ou un storyboard en tant que sous-vue de l'élément
view
d'un ViewController qui utilise autolayout, puis en mettant votresizeToFit
l'appel enviewDidLoad
ne fonctionnera pas, car autolayout dimensionne et positionne les sous-vues aprèsviewDidLoad
est appelé et annulera immédiatement les effets de votresizeToFit
appel. Cependant, l'appelsizeToFit
de l'intérieurviewDidLayoutSubviews
sera travail.
Ma réponse originale (pour la postérité/référence) :
Cela utilise le NSString
méthode sizeWithFont:constrainedToSize:lineBreakMode:
pour calculer la hauteur du cadre nécessaire à l'insertion d'une chaîne, puis définit l'origine et la largeur.
Redimensionnez le cadre de l'étiquette en utilisant le texte que vous voulez insérer. De cette façon, vous pouvez accueillir n'importe quel nombre de lignes.
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;
Cette page contient un code différent pour la même solution :
1) Définissez le nouveau texte :
myLabel.text = @"Some Text"
2) Réglez le maximum number
de lignes à 0 (automatique) :
myLabel.numberOfLines = 0
3) Réglez le cadre de l'étiquette à la taille maximale :
myLabel.frame = CGRectMake(20,20,200,800)
4) Appel sizeToFit
pour réduire la taille du cadre afin que le contenu s'adapte parfaitement :
[myLabel sizeToFit]
Le cadre des étiquettes est maintenant juste assez haut et large pour accueillir votre texte. Le coin supérieur gauche ne devrait pas être modifié. J'ai testé ceci uniquement avec du texte aligné en haut à gauche. Pour d'autres alignements, vous devrez peut-être modifier le cadre par la suite.
De plus, l'habillage des mots est activé sur mon étiquette.
Au cas où cela pourrait aider quelqu'un, j'ai eu le même problème mais j'ai pu le résoudre simplement en passant de l'utilisation de l'option UILabel
à l'utilisation UITextView
. Je comprends que ce n'est pas pour tout le monde parce que la fonctionnalité est un peu différente.
Si vous passez à l'utilisation de UITextView
Si vous voulez que la fenêtre se comporte comme une étiquette, vous pouvez désactiver toutes les propriétés de la vue défilante ainsi que l'interaction de l'utilisateur activée... Cela l'obligera à se comporter davantage comme une étiquette.
En ce qui concerne la solution d'extension :
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
doit être remplacé par
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n "];
Un espace supplémentaire est nécessaire dans chaque nouvelle ligne ajoutée, car l'iPhone UILabels
Les retours chariot de fin de ligne semblent être ignorés :(
De la même manière, alignBottom doit être mis à jour également avec un @" \n@%"
à la place de "\n@%"
(l'initialisation du cycle doit être remplacée par "for(int i=0..." aussi).
L'extension suivante fonctionne pour moi :
// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end
// -- file: UILabel+VerticalAlign.m
@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
Ensuite, appelez [yourLabel alignTop];
ou [yourLabel alignBottom];
après chaque affectation de votre texteLabel.
Comme la réponse ci-dessus, mais ce n'était pas tout à fait juste, ou facile à mettre dans le code, alors je l'ai nettoyé un peu. Ajoutez cette extension soit dans son propre fichier .h et .m, soit en la collant juste au-dessus de l'implémentation que vous souhaitez utiliser :
#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
Ensuite, pour l'utiliser, mettez votre texte dans l'étiquette, puis appelez la méthode appropriée pour l'aligner :
[myLabel alignTop];
ou
[myLabel alignBottom];
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.