J'essaie d'aligner verticalement le texte dans la vue UILabel de mon application. Le problème est que je veux que le texte soit aligné verticalement vers le haut et que la taille de l'étiquette soit de 280 x 150. Je ne peux réaliser qu'une de ces deux choses. Si je supprime la ligne
[myLabel sizeToFit];
alors l'alignement du texte est correct mais la taille est foirée. Mais si j'ajoute la ligne ci-dessus, l'alignement est altéré mais la taille est correcte. Comment puis-je résoudre ce problème.
J'ai ajouté le code ci-dessous -
CGRect labelFrame = CGRectMake(22, 50, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setText:finalRecipe];
[myLabel setBackgroundColor: [UIColor lightGrayColor]];
[myLabel setNumberOfLines:0];
[myLabel sizeToFit];
[self.view addSubview:myLabel];
Je suis l'auteur de FXLabel et, même si je ne connais pas Manish, je crois qu'il essayait de l'aider (s'il me faisait de la publicité, je ne le lui ai certainement pas demandé et je ne le paye pas - désolé Manish!).
L'une des fonctionnalités de FXLabel est qu'il respecte la propriété UIContentMode de l'étiquette, telle que définie dans le générateur Interface. Cela signifie que vous pouvez définir label.contentMode = UIViewContentModeTop; pour aligner le texte en haut de la vue des étiquettes (ce qui ne fonctionne pas pour un UILabel standard). L'exemple pertinent est ici:
https://github.com/nicklockwood/FXLabel/tree/master/Examples/Text%20Alignment
FXLabel est une sous-classe de UILabel, donc je pense que c'est une très bonne solution pour la question posée. Cependant, si l’affiche préfère résoudre le problème sans utiliser de bibliothèque tierce (ce qui est compréhensible), voici le code pour le faire:
CGRect labelFrame = CGRectMake(22, 50, 280, 150);
UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
[myLabel setText:finalRecipe];
[myLabel setBackgroundColor: [UIColor lightGrayColor]];
[myLabel setNumberOfLines:0];
CGFloat fontSize = 0.0f;
labelFrame.size = [myLabel.text sizeWithFont:myLabel.font
minFontSize:myLabel.minimumFontSize
actualFontSize:&fontSize
forWidth:labelFrame.width
lineBreakMode:myLabel.lineBreakMode];
myLabel.frame = labelFrame;
[self.view addSubview:myLabel];
Note: (Ceci n'est pas testé, donc excuses s'il y a des fautes de frappe)
ne pas utiliser UILabel
pour cela. Utilisez UIButton
avec UserInteractionEnabled = NO;
et qui dispose d'options pour aligner le texte verticalement ou horizontalement.
Voici:
btnDetail.titleLabel?.numberOfLines = 5
btnDetail.titleLabel?.lineBreakMode = .byCharWrapping
btnDetail.contentVerticalAlignment = .top
btnDetail.contentHorizontalAlignment = .left
btnDetail.isUserInteractionEnabled = false
btnDetail.autoresizesSubviews = true
btnDetail.autoresizingMask = .flexibleWidth
[btnDetail.titleLabel setNumberOfLines:5];
[btnDetail.titleLabel setLineBreakMode:NSLineBreakByCharWrapping];
[btnDetail setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
[btnDetail setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[btnDetail setUserInteractionEnabled:NO];
btnDetail.autoresizesSubviews = YES;
btnDetail.autoresizingMask = UIViewAutoresizingFlexibleWidth;
Vous devrez sous-classer UILabel. Essaye ça:
- (void)drawTextInRect:(CGRect)rect
{
CGSize sizeThatFits = [self sizeThatFits:rect.size];
rect.size.height = MIN(rect.size.height, sizeThatFits.height);
[super drawTextInRect:rect];
}
Comme vous l'avez découvert, UILabel centre verticalement le texte dans ses limites. Ici, nous demandons à -sizeThatFits
la taille du bloc de texte et l’utilisons pour contraindre le rectangle de dessin transmis à UILabel, de sorte que le texte soit tracé à partir du haut des limites de l’étiquette.
Vous pouvez même supporter la propriété contentMode
ignorée (soupir) comme ceci:
- (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];
}
Il existe de nombreuses autres solutions et discussions ici: Aligner verticalement le texte en haut dans un UILabel
Dans Swift, la solution du JRC de sous-classer UILabel
, de remplacer drawTextInRect
et de se conformer à UIViewContentMode
ressemblerait à ceci:
class AlignableUILabel: UILabel {
override func drawText(in rect: CGRect) {
var newRect = CGRect(x: rect.Origin.x,y: rect.Origin.y,width: rect.width, height: rect.height)
let fittingSize = sizeThatFits(rect.size)
if contentMode == UIViewContentMode.top {
newRect.size.height = min(newRect.size.height, fittingSize.height)
} else if contentMode == UIViewContentMode.bottom {
newRect.Origin.y = max(0, newRect.size.height - fittingSize.height)
}
super.drawText(in: newRect)
}
}
La mise en œuvre est simplement une question de:
yourLabel.contentMode = UIViewContentMode.top
Pour moi, cela a fonctionné comme un charme.
Il existe un moyen de ne pas sous-classer, en utilisant un bouton ou en roulant le vôtre.
définissez le nombre de lignes sur 0, puis appelez sizeToFit.
[label setNumberOfLines:0];
[label sizeToFit];
Plus de détails ici comme je pense que quelqu'un d'autre est lié à: Aligner verticalement le texte en haut dans un UILabel
Vous pouvez le faire avec une contrainte sur le constructeur d'interface.
J'espère que cela vous aidera!
Beau bidouillage ... mes deux sous pour Swift 4.2/5:
self.optTextMessage.numberOfLines = 0
self.optTitle.lineBreakMode = .byWordWrapping
et ajoutez\n .. comme suggéré ..
Je l'ai fait ce que vous voulez en implémentant une catégorie:
.h
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end
.m
@implementation UILabel (VerticalAlign)
#pragma mark
#pragma mark - Align Methods
- (void)alignTop
{
[self setFrame:[self newLabelFrame:UIControlContentVerticalAlignmentTop]];
}
- (void)alignBottom
{
[self setFrame:[self newLabelFrame:UIControlContentVerticalAlignmentBottom]];
}
#pragma mark
#pragma mark - Helper Methods
- (CGRect)newLabelFrame:(UIControlContentVerticalAlignment)alignment
{
CGRect labelRect = self.frame;
NSStringDrawingOptions options = NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesFontLeading;
CGRect textRect = [self.text boundingRectWithSize:CGSizeMake(227.f, CGFLOAT_MAX)
options:options
attributes:@{NSFontAttributeName:self.font}
context:nil];
CGFloat textOffset = labelRect.size.height - textRect.size.height;
UIEdgeInsets contentInsets;
if (alignment == UIControlContentVerticalAlignmentTop)
{
if (textOffset < (labelRect.size.height/2.f))
{
contentInsets = UIEdgeInsetsMake(-textOffset, 0.f, 0.f, 0.f);
}
else
{
contentInsets = UIEdgeInsetsMake(0.f, 0.f, textOffset, 0.f);
}
}
else
{
if (textOffset < (labelRect.size.height/2.f))
{
contentInsets = UIEdgeInsetsMake(0.f, 0.f, -textOffset, 0.f);
}
else
{
contentInsets = UIEdgeInsetsMake(textOffset, 0.f, 0.f, 0.f);
}
}
return UIEdgeInsetsInsetRect(labelRect, contentInsets);
}
@end
N'oubliez pas que vous devez définir "NumberOfLines" sur 0. Cet exemple fonctionne avec les options multilignes!
Après avoir implémenté la catégorie ci-dessus, vous pouvez simplement faire:
[myLabel setText:finalRecipe];
[myLabel alignTop];
À votre santé!