2342 votes

Aligner verticalement le texte dans un 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 ?

enter image description here

2775voto

nevan king Points 46410

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];

sizeToFit to squeeze a label


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];

Longer label text with 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];

enter image description here

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;

label alignment


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.

Correct label alignment by resizing the frame width

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 votre sizeToFit l'appel en viewDidLoad ne fonctionnera pas, car autolayout dimensionne et positionne les sous-vues après viewDidLoad est appelé et annulera immédiatement les effets de votre sizeToFit appel. Cependant, l'appel sizeToFit de l'intérieur viewDidLayoutSubviews 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 :

discussions sur la pomme

345voto

Jakob Egger Points 4282

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.

166voto

jowie Points 3733

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.

164voto

D.S. Points 1207

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.

83voto

BadPirate Points 11614

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.com

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.

Powered by:

X