Réponses:
Il n'y a aucun moyen de définir l'alignement vertical sur a UILabel
, mais vous pouvez obtenir le même effet en modifiant le cadre de l'étiquette. J'ai fait mes étiquettes en orange pour que vous puissiez voir clairement ce qui se passe.
Voici le moyen rapide et facile de le faire:
[myLabel sizeToFit];
Si vous avez une étiquette avec un texte plus long qui fera plus d'une ligne, définissez numberOfLines
sur 0
(zéro ici signifie un nombre illimité de lignes).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Version plus longue
Je vais créer mon étiquette en code afin que vous puissiez voir ce qui se passe. Vous pouvez également configurer la plupart de cela dans Interface Builder. Ma configuration est une application basée sur la vue avec une image d'arrière-plan que j'ai créée dans Photoshop pour afficher 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 d'utilisation sizeToFit
entrent en jeu avec le 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 enregistrer la largeur de l'étiquette d'origine dans une variable et la définir après 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
cela respectera la largeur minimale de votre étiquette initiale. Si vous commencez avec une étiquette de 100 de large et que vous l'appelez sizeToFit
, cela vous donnera une étiquette (peut-être très grande) de 100 (ou un peu moins) de largeur. Vous souhaiterez peut-être définir votre étiquette à la largeur minimale souhaitée avant de redimensionner.
Quelques autres choses à noter:
Le lineBreakMode
respect dépend de la façon dont il est défini. NSLineBreakByTruncatingTail
(par défaut) est ignoré après sizeToFit
, de même que les deux autres modes de troncature (tête et milieu). NSLineBreakByClipping
est également ignoré. 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 NIB et les storyboards utilisant la disposition automatique dans les commentaires:
Si votre étiquette est incluse dans une plume ou un storyboard en tant que sous-vue d'
view
un ViewController qui utilise la mise en page automatique, alors placer votresizeToFit
appelviewDidLoad
ne fonctionnera pas, car la mise en page automatique taille et positionne les sous-vues aprèsviewDidLoad
est appelée et annulera immédiatement les effets de votresizeToFit
appel. Toutefois, l' appelsizeToFit
de l' intérieurviewDidLayoutSubviews
volonté travail.
Cela utilise la NSString
méthode sizeWithFont:constrainedToSize:lineBreakMode:
pour calculer la hauteur du cadre nécessaire pour s'adapter à une chaîne, puis définit l'origine et la largeur.
Redimensionnez le cadre de l'étiquette en utilisant le texte que vous souhaitez 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;
adjustsFontSizeToFitWidth
utilisez alors sizeToFit, puis définissez le cadre de l'étiquette sur 0, 0, theWidthYouWant, label.frame.size.height (qui est la nouvelle hauteur déterminée par sizeToFit) ALORS appliqueradjustsFontSizeToFitWidth
Définissez le nouveau texte:
myLabel.text = @"Some Text"
Réglez les maximum number
lignes sur 0 (automatique):
myLabel.numberOfLines = 0
Réglez le cadre de l'étiquette à la taille maximale:
myLabel.frame = CGRectMake(20,20,200,800)
Appelez sizeToFit
pour réduire la taille du cadre afin que le contenu corresponde:
[myLabel sizeToFit]
Le cadre des étiquettes est maintenant juste assez haut et large pour s'adapter à votre texte. Le coin supérieur gauche doit rester inchangé. J'ai testé cela uniquement avec le texte aligné en haut à gauche. Pour les autres alignements, vous devrez peut-être modifier le cadre par la suite.
En outre, mon étiquette a activé l'habillage de mots.
En référence à la solution d'extension:
for(int i=1; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:@"\n"];
devrait ê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 UILabels
les retours de chariot de l' iPhone semblent être ignorés :(
De même, alignBottom doit également être mis à jour avec un @" \n@%"
à la place de "\n@%"
(pour l'initialisation du cycle doit être remplacé 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
Appelez ensuite [yourLabel alignTop];
ou [yourLabel alignBottom];
après chaque affectation de texte yourLabel.
VerticalAlign
entre parenthèses après @implementation UILabel
. Étant nouveau dans Objective-C, je n'avais jamais rencontré cette syntaxe auparavant. Comment ça s'appelle?
sizeWithFont:constrainedToSize:lineBreakMode:
et sizeWithFont: sont toutes deux dépréciées dans iOS7. En outre, cette catégorie ne fonctionne que sur les étiquettes lorsque numberOfLines est supérieur à 0.
Juste au cas où cela aiderait quelqu'un, j'ai eu le même problème mais j'ai pu résoudre le problème simplement en passant de l'utilisation UILabel
à l'utilisation UITextView
. J'apprécie que ce n'est pas pour tout le monde car la fonctionnalité est un peu différente.
Si vous passez à l'utilisation UITextView
, vous pouvez désactiver toutes les propriétés de la vue de défilement ainsi que l'interaction utilisateur activée ... Cela l'obligera à agir davantage comme une étiquette.
UITextView
m'a donné le résultat souhaité tout de suite.
Pas de bruit, pas de bruit
@interface MFTopAlignedLabel : UILabel
@end
@implementation MFTopAlignedLabel
- (void)drawTextInRect:(CGRect) rect
{
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
rect.size.height = [attributedText boundingRectWithSize:rect.size
options:NSStringDrawingUsesLineFragmentOrigin
context:nil].size.height;
if (self.numberOfLines != 0) {
rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
}
[super drawTextInRect:rect];
}
@end
Pas de bruit, pas d'Objective-c, pas de bruit mais Swift 3:
class VerticalTopAlignLabel: UILabel {
override func drawText(in rect:CGRect) {
guard let labelText = text else { return super.drawText(in: rect) }
let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
var newRect = rect
newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height
if numberOfLines != 0 {
newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
}
super.drawText(in: newRect)
}
}
Swift 4.2
class VerticalTopAlignLabel: UILabel {
override func drawText(in rect:CGRect) {
guard let labelText = text else { return super.drawText(in: rect) }
let attributedText = NSAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font])
var newRect = rect
newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height
if numberOfLines != 0 {
newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
}
super.drawText(in: newRect)
}
}
Comme la réponse ci-dessus, mais ce n'était pas tout à fait correct, ou facile à insérer dans le code, donc je l'ai nettoyé un peu. Ajoutez cette extension à ses propres fichiers .h et .m ou collez-la 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
Et puis pour utiliser, mettez votre texte dans l'étiquette, puis appelez la méthode appropriée pour l'aligner:
[myLabel alignTop];
ou
[myLabel alignBottom];
Un moyen encore plus rapide (et plus sale) d'accomplir cela est de définir le mode de saut de ligne de l'UILabel sur "Clip" et d'ajouter une quantité fixe de nouvelles lignes.
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
Cette solution ne fonctionnera pas pour tout le monde - en particulier, si vous souhaitez toujours afficher "..." à la fin de votre chaîne si elle dépasse le nombre de lignes que vous affichez, vous devrez utiliser l'une des les morceaux de code les plus longs - mais pour de nombreux cas, cela vous fournira ce dont vous avez besoin.
UILineBreakModeWordWrap
plutôt.
Approche la plus simple avec Storyboard:
Incorporez une étiquette dans StackView et définissez les deux attributs suivants de StackView dans l'inspecteur d'attributs:
1- Axis
à Horizontal
,
2- Alignment
àTop
UILabel
dans une UIView
sous-classe ( UIView
ordinaire suffit généralement) et laisser cette étiquette se développer dans le sens descendant. Merci!
UILabel
et laisser le StackView faire son travail. Merci!
Au lieu de UILabel
vous pouvez utiliser UITextField
ce qui a l'option d'alignement vertical:
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
Je lutte depuis longtemps avec celui-ci et je voulais partager ma solution.
Cela vous donnera un UILabel
texte qui rétrécira automatiquement jusqu'à 0,5 échelle et centrera verticalement le texte. Ces options sont également disponibles dans Storyboard / IB.
[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
Créer une nouvelle classe
LabelTopAlign
fichier .h
#import <UIKit/UIKit.h>
@interface KwLabelTopAlign : UILabel {
}
@end
fichier .m
#import "KwLabelTopAlign.h"
@implementation KwLabelTopAlign
- (void)drawTextInRect:(CGRect)rect {
int lineHeight = [@"IglL" sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, 9999.0f)].height;
if(rect.size.height >= lineHeight) {
int textHeight = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, rect.size.height)].height;
int yMax = textHeight;
if (self.numberOfLines > 0) {
yMax = MIN(lineHeight*self.numberOfLines, yMax);
}
[super drawTextInRect:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, yMax)];
}
}
@end
Voici une implémentation plus simple qui fait de même:
#import "KwLabelTopAlign.h"
@implementation KwLabelTopAlign
- (void)drawTextInRect:(CGRect)rect
{
CGFloat height = [self.text sizeWithFont:self.font
constrainedToSize:rect.size
lineBreakMode:self.lineBreakMode].height;
if (self.numberOfLines != 0) {
height = MIN(height, self.font.lineHeight * self.numberOfLines);
}
rect.size.height = MIN(rect.size.height, height);
[super drawTextInRect:rect];
}
@end
sizeToFit
solutions ce qui rend en fait la UILabel
mettre tout texte en haut, même si vous remplacez dynamiquement un texte plus court avec une plus ou vice versa.
Dans Interface Builder
UILabel
à la taille du plus grand texte possibleLines
sur «0» dans l'inspecteur d'attributsDans votre code
sizeToFit
sur votre étiquetteExtrait de code:
self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
Pour l'interface utilisateur adaptative (iOS8 ou version ultérieure), l'alignement vertical de UILabel doit être défini à partir de StoryBoard en modifiant les propriétés
noOfLines
= 0 et
Contraintes
Ajustement des contraintes UILabel LefMargin, RightMargin et Top Margin.
Changement
Content Compression Resistance Priority For Vertical
= 1000` Pour que Vertical> Horizontal.
Édité:
noOfLines=0
et les contraintes suivantes sont suffisantes pour obtenir les résultats souhaités.
Créez une sous-classe de UILabel. Fonctionne comme un charme:
// TopLeftLabel.h
#import <Foundation/Foundation.h>
@interface TopLeftLabel : UILabel
{
}
@end
// TopLeftLabel.m
#import "TopLeftLabel.h"
@implementation TopLeftLabel
- (id)initWithFrame:(CGRect)frame
{
return [super initWithFrame:frame];
}
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
textRect.origin.y = bounds.origin.y;
return textRect;
}
-(void)drawTextInRect:(CGRect)requestedRect
{
CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:actualRect];
}
@end
Comme discuté ici .
J'ai écrit une fonction util pour atteindre cet objectif. Vous pouvez jeter un œil:
// ajuste la hauteur d'une étiquette multi-lignes pour l'aligner verticalement avec le haut + (void) alignLabelWithTop: (UILabel *) label { CGSize maxSize = CGSizeMake (label.frame.size.width, 999); label.adjustsFontSizeToFitWidth = NO; // obtenir la hauteur réelle CGSize actualSize = [label.text sizeWithFont: label.font constrainedToSize: maxSize lineBreakMode: label.lineBreakMode]; CGRect rect = label.frame; rect.size.height = actualSize.height; label.frame = rect; }
.Comment utiliser? (Si lblHello est créé par le générateur d'interface, je saute donc certains détails des attributs UILabel)
lblHello.text = @ "Bonjour tout le monde! Bonjour tout le monde! Bonjour tout le monde! Bonjour tout le monde! Bonjour tout le monde! Bonjour tout le monde! Bonjour tout le monde! Bonjour tout le monde!"; lblHello.numberOfLines = 5; [Utils alignLabelWithTop: lblHello];
Je l'ai également écrit sur mon blog en tant qu'article : http://fstoke.me/blog/?p=2819
J'ai pris un certain temps pour lire le code, ainsi que le code de la page introduite, et j'ai constaté qu'ils essayaient tous de modifier la taille du cadre de l'étiquette, afin que l'alignement vertical central par défaut n'apparaisse pas.
Cependant, dans certains cas, nous voulons que l'étiquette occupe tous ces espaces, même si l'étiquette contient beaucoup de texte (par exemple, plusieurs lignes de même hauteur).
Ici, j'ai utilisé une autre façon de le résoudre, en remplissant simplement les sauts de ligne jusqu'à la fin de l'étiquette (veuillez noter que j'ai hérité de la UILabel
, mais ce n'est pas nécessaire):
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 "];
}
J'ai pris les suggestions ici et créé une vue qui peut envelopper un UILabel et le dimensionner et définir le nombre de lignes afin qu'il soit aligné en haut. Mettez simplement un UILabel comme sous-vue:
@interface TopAlignedLabelContainer : UIView
{
}
@end
@implementation TopAlignedLabelContainer
- (void)layoutSubviews
{
CGRect bounds = self.bounds;
for (UILabel *label in [self subviews])
{
if ([label isKindOfClass:[UILabel class]])
{
CGSize fontSize = [label.text sizeWithFont:label.font];
CGSize textSize = [label.text sizeWithFont:label.font
constrainedToSize:bounds.size
lineBreakMode:label.lineBreakMode];
label.numberOfLines = textSize.height / fontSize.height;
label.frame = CGRectMake(0, 0, textSize.width,
fontSize.height * label.numberOfLines);
}
}
}
@end
Vous pouvez utiliser TTTAttributedLabel , il prend en charge l'alignement vertical.
@property (nonatomic) TTTAttributedLabel* label;
<...>
//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
J'ai trouvé que les réponses à cette question sont maintenant un peu obsolètes, alors ajoutez cela pour les fans de mise en page automatique.
La mise en page automatique rend ce problème assez trivial. En supposant que nous ajoutons l'étiquette à UIView *view
, le code suivant accomplira cela:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setText:@"Some text here"];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:label];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@{@"label": label}]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@{@"label": label}]];
La hauteur de l'étiquette sera calculée automatiquement (en l'utilisant intrinsicContentSize
) et l'étiquette sera positionnée bord à bord horizontalement, en haut de la view
.
J'ai utilisé beaucoup des méthodes ci-dessus, et je veux juste ajouter une approche rapide et sale que j'ai utilisée:
myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
Assurez-vous que le nombre de sauts de ligne dans la chaîne entraînera tout texte à remplir l'espace vertical disponible et définissez le UILabel pour tronquer tout texte débordant.
Parce que parfois assez bon est assez bon .
UITextView
c'est qu'il peut appeler dlopen
afin de prendre en charge la saisie de texte. Cela peut entraîner un retard important sur le thread d'interface utilisateur, donc cette approche est beaucoup plus performante!
Je voulais avoir une étiquette capable d'avoir plusieurs lignes, une taille de police minimale et centrée horizontalement et verticalement dans sa vue parent. J'ai ajouté mon étiquette par programme à ma vue:
- (void) customInit {
// Setup label
self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
self.label.numberOfLines = 0;
self.label.lineBreakMode = UILineBreakModeWordWrap;
self.label.textAlignment = UITextAlignmentCenter;
// Add the label as a subview
self.autoresizesSubviews = YES;
[self addSubview:self.label];
}
Et puis quand j'ai voulu changer le texte de mon étiquette ...
- (void) updateDisplay:(NSString *)text {
if (![text isEqualToString:self.label.text]) {
// Calculate the font size to use (save to label's font)
CGSize textConstrainedSize = CGSizeMake(self.frame.size.width, INT_MAX);
self.label.font = [UIFont systemFontOfSize:TICKER_FONT_SIZE];
CGSize textSize = [text sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
while (textSize.height > self.frame.size.height && self.label.font.pointSize > TICKER_MINIMUM_FONT_SIZE) {
self.label.font = [UIFont systemFontOfSize:self.label.font.pointSize-1];
textSize = [ticker.blurb sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
}
// In cases where the frame is still too large (when we're exceeding minimum font size),
// use the views size
if (textSize.height > self.frame.size.height) {
textSize = [text sizeWithFont:self.label.font constrainedToSize:self.frame.size];
}
// Draw
self.label.frame = CGRectMake(0, self.frame.size.height/2 - textSize.height/2, self.frame.size.width, textSize.height);
self.label.text = text;
}
[self setNeedsDisplay];
}
J'espère que cela aide quelqu'un!
FXLabel (sur github) le fait hors de la boîte en définissant label.contentMode
sur UIViewContentModeTop
. Ce composant n'est pas fait par moi, mais c'est un composant que j'utilise fréquemment et qui a des tonnes de fonctionnalités, et semble bien fonctionner.
pour quiconque lit ceci parce que le texte à l'intérieur de votre étiquette n'est pas centré verticalement, gardez à l'esprit que certains types de polices ne sont pas conçus de la même manière. par exemple, si vous créez une étiquette de taille zapfino 16, vous verrez que le texte n'est pas parfaitement centré verticalement.
cependant, travailler avec helvetica centrera verticalement votre texte.
Utilisez textRect(forBounds:limitedToNumberOfLines:)
.
class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
super.drawText(in: textRect)
}
}
Sous-classe UILabel et contraignez le rectangle de dessin, comme ceci:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
J'ai essayé la solution impliquant un remplissage de nouvelle ligne et j'ai rencontré un comportement incorrect dans certains cas. D'après mon expérience, il est plus facile de contraindre le rect rectangle comme ci-dessus que de jouer avec numberOfLines
.
PS Vous pouvez imaginer facilement supporter UIViewContentMode de cette façon:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
if (self.contentMode == UIViewContentModeTop) {
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
}
else if (self.contentMode == UIViewContentModeBottom) {
rect.origin.y = MAX(0, rect.size.height - sizeThatFits.height);
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
}
[super drawTextInRect:rect];
}
En bref,
let myLabel : UILabel!
Pour que votre texte de votre étiquette s'adapte à l'écran et qu'il se trouve en haut
myLabel.sizeToFit()
Pour que votre police d'étiquette s'adapte à la largeur de l'écran ou à une largeur spécifique.
myLabel.adjustsFontSizeToFitWidth = YES
et certains textAlignment pour l'étiquette:
myLabel.textAlignment = .center
myLabel.textAlignment = .left
myLabel.textAlignment = .right
myLabel.textAlignment = .Natural
myLabel.textAlignment = .Justified
[myLabel sizeToFit]
. Je vous remercie!
Ceci est une ancienne solution, utilisez la mise en page automatique sur iOS> = 6
Ma solution:
@interface UITopAlignedLabel : UILabel
@end
@implementation UITopAlignedLabel
#pragma mark Instance methods
- (NSArray*)splitTextToLines:(NSUInteger)maxLines {
float width = self.frame.size.width;
NSArray* words = [self.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray* lines = [NSMutableArray array];
NSMutableString* buffer = [NSMutableString string];
NSMutableString* currentLine = [NSMutableString string];
for (NSString* word in words) {
if ([buffer length] > 0) {
[buffer appendString:@" "];
}
[buffer appendString:word];
if (maxLines > 0 && [lines count] == maxLines - 1) {
[currentLine setString:buffer];
continue;
}
float bufferWidth = [buffer sizeWithFont:self.font].width;
if (bufferWidth < width) {
[currentLine setString:buffer];
}
else {
[lines addObject:[NSString stringWithString:currentLine]];
[buffer setString:word];
[currentLine setString:buffer];
}
}
if ([currentLine length] > 0) {
[lines addObject:[NSString stringWithString:currentLine]];
}
return lines;
}
- (void)drawRect:(CGRect)rect {
if ([self.text length] == 0) {
return;
}
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, self.textColor.CGColor);
CGContextSetShadowWithColor(context, self.shadowOffset, 0.0f, self.shadowColor.CGColor);
NSArray* lines = [self splitTextToLines:self.numberOfLines];
NSUInteger numLines = [lines count];
CGSize size = self.frame.size;
CGPoint origin = CGPointMake(0.0f, 0.0f);
for (NSUInteger i = 0; i < numLines; i++) {
NSString* line = [lines objectAtIndex:i];
if (i == numLines - 1) {
[line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeTailTruncation];
}
else {
[line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeClip];
}
origin.y += self.font.lineHeight;
if (origin.y >= size.height) {
return;
}
}
}
@end