Comment définir l'alignment en haut à gauche pour UILabel pour l'application iOS?

J'ai ajouté une label dans mon file nib, puis il est nécessaire d'avoir un alignment en haut à gauche pour ce lable. Comme je fournis du text à l'exécution, je ne suis pas certain qu'il y ait autant de lignes. Ainsi, si le text ne contient qu'une seule ligne, il apparaît comme aligné sur le centre vertical. Cet alignment ne correspond pas à mon lable respectif devant lui.

Par exemple:

entrez la description de l'image ici

Ce qui est étrange 🙁

Est-il possible de définir un text d'label approprié pour l'alignment en haut à gauche?

Plutôt que de ré-expliquer, je vais lier à cette question / réponse assez vaste et hautement cotée:

Aligner verticalement le text au sumt d'un UILabel

La réponse courte est non, Apple n'a pas rendu cela facile, mais c'est possible en changeant la taille du cadre.

C'est assez facile à faire. Créez une sous- UILabel UILabel avec une propriété verticalAlignment et remplacez textRectForBounds:limitedToNumberOfLines pour renvoyer les limites correctes pour un alignment vertical supérieur, intermédiaire ou inférieur. Voici le code:

SOLabel.h

 #import <UIKit/UIKit.h> typedef enum { VerticalAlignmentTop = 0, // default VerticalAlignmentMiddle, VerticalAlignmentBottom, } VerticalAlignment; @interface SOLabel : UILabel @property (nonatomic, readwrite) VerticalAlignment verticalAlignment; @end 

SOLabel.m

 @implementation SOLabel -(id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (!self) return nil; // set inital value via IVAR so the setter isn't called _verticalAlignment = VerticalAlignmentTop; return self; } -(VerticalAlignment) verticalAlignment { return _verticalAlignment; } -(void) setVerticalAlignment:(VerticalAlignment)value { _verticalAlignment = value; [self setNeedsDisplay]; } // align text block according to vertical alignment settings -(CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines { CGRect rect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines]; CGRect result; switch (_verticalAlignment) { case VerticalAlignmentTop: result = CGRectMake(bounds.origin.x, bounds.origin.y, rect.size.width, rect.size.height); break; case VerticalAlignmentMiddle: result = CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height); break; case VerticalAlignmentBottom: result = CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height), rect.size.width, rect.size.height); break; default: result = bounds; break; } return result; } -(void)drawTextInRect:(CGRect)rect { CGRect r = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines]; [super drawTextInRect:r]; } @end 

Le SOLabel fonctionne pour moi.

Swift 1:

 class UIVerticalAlignLabel: UILabel { enum VerticalAlignment : Int { case VerticalAlignmentTop = 0 case VerticalAlignmentMiddle = 1 case VerticalAlignmentBottom = 2 } var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop { didSet { setNeedsDisplay() } } required init(coder aDecoder: NSCoder){ super.init(coder: aDecoder) } override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect { let rect = super.textRectForBounds(bounds, limitedToNumberOfLines: limitedToNumberOfLines) switch(verticalAlignment) { case .VerticalAlignmentTop: return CGRectMake(bounds.origin.x, bounds.origin.y, rect.size.width, rect.size.height) case .VerticalAlignmentMiddle: return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height) case .VerticalAlignmentBottom: return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height), rect.size.width, rect.size.height) default: return bounds } } override func drawTextInRect(rect: CGRect) { let r = self.textRectForBounds(rect, limitedToNumberOfLines: self.numberOfLines) super.drawTextInRect(r) } } 

Swift 3:

Cette version a été mise à jour depuis l'original pour permettre le support des langages RTL:

 public class VerticalAlignLabel: UILabel { enum VerticalAlignment { case top case middle case bottom } var verticalAlignment : VerticalAlignment = .top { didSet { setNeedsDisplay() } } override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect { let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines) if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft { switch verticalAlignment { case .top: return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height) case .middle: return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height) case .bottom: return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height) } } else { switch verticalAlignment { case .top: return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height) case .middle: return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height) case .bottom: return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height) } } } override public func drawText(in rect: CGRect) { let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines) super.drawText(in: r) } } 

J'ai trouvé une solution utilisant AutoLayout dans StoryBoard.

1) Définissez le nombre de lignes sur 0 et l'alignment du text sur Gauche.

entrez la description de l'image ici

2) Définir la contrainte de hauteur.

entrez la description de l'image ici

3) La contrainte de hauteur doit être en relation – inférieure ou égale

entrez la description de l'image ici

4)

  override func viewWillLayoutSubviews() { sampleLabel.sizeToFit() } 

J'ai obtenu le résultat comme suit:

entrez la description de l'image ici

Dans votre code

 label.text = @"some text"; [label sizeToFit]; 

Sachez que si vous l'utilisez dans des cellules de tableau ou dans d'autres vues recykeyes avec des données différentes, vous devrez stocker l'image d'origine quelque part et la réinitialiser avant d'appeler sizeToFit.

J'avais aussi ce problème, mais ce que j'ai trouvé, c'est l'ordre dans lequel vous définissez les propriétés et les methods de UILabel!

Si vous appelez [label sizeToFit] avant label.font = [UIFont fontWithName:@"Helvetica" size:14]; alors le text ne s'aligne pas au sumt mais si vous les échangez, alors c'est le cas!

J'ai également remarqué que la définition du text en premier fait aussi une différence.

J'espère que cela t'aides.

J'ai trouvé une autre solution pour le même problème. J'ai utilisé UITextView au lieu de UILabel et ai changé la fonction editable () à false.

Lorsque vous utilisez le constructor d'interface, définissez les contraintes pour votre label (veillez également à définir la hauteur et la largeur). Ensuite, dans l'inspecteur de taille, vérifiez la hauteur de l'label. Là vous voudrez qu'il lise> = au lieu de =. Ensuite, dans l'implémentation pour ce controller de vue, définissez le nombre de lignes à 0 (peut également être fait dans IB) et définissez l'label [label sizeToFit]; et à mesure que votre text gagne en longueur, l'label s'agrandira et gardera votre text en haut à gauche.

Solution avec SoLabel fonctionne, merci.

Ci-dessous j'ai ajouté la version monotouch:

  public class UICustomLabel : UILabel { private UITextVerticalAlignment _textVerticalAlignment; public UICustomLabel() { TextVerticalAlignment = UITextVerticalAlignment.Top; } public UITextVerticalAlignment TextVerticalAlignment { get { return _textVerticalAlignment; } set { _textVerticalAlignment = value; SetNeedsDisplay(); } } public override void DrawText(RectangleF rect) { var bound = TextRectForBounds(rect, Lines); base.DrawText(bound); } public override RectangleF TextRectForBounds(RectangleF bounds, int numberOfLines) { var rect = base.TextRectForBounds(bounds, numberOfLines); RectangleF resultRect; switch (TextVerticalAlignment) { case UITextVerticalAlignment.Top: resultRect = new RectangleF(bounds.X, bounds.Y, rect.Size.Width, rect.Size.Height); break; case UITextVerticalAlignment.Middle: resultRect = new RectangleF(bounds.X, bounds.Y + (bounds.Size.Height - rect.Size.Height)/2, rect.Size.Width, rect.Size.Height); break; case UITextVerticalAlignment.Bottom: resultRect = new RectangleF(bounds.X, bounds.Y + (bounds.Size.Height - rect.Size.Height), rect.Size.Width, rect.Size.Height); break; default: resultRect = bounds; break; } return resultRect; } } public enum UITextVerticalAlignment { Top = 0, // default Middle, Bottom } 

La manière la plus simple et la plus simple consiste à incorporer Label dans StackView et à définir l'axe de StackView sur Horizontal, Alignment to Top dans l'inspecteur d'attributes de Storyboard, comme illustré ici .

Pour iOS 7 c'est ce que j'ai fait et travaillé pour moi

 @implementation UILabel (VerticalAlign) - (void)alignTop { CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX); NSDictionary *atsortingbutes = @{NSFontAtsortingbuteName : self.font}; CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSSsortingngDrawingUsesLineFragmentOrigin | NSSsortingngDrawingUsesFontLeading atsortingbutes:atsortingbutes context:nil]; int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight); CGRect newFrame = self.frame; newFrame.size.height = numberOfLines * self.font.lineHeight; self.frame = newFrame; } - (void)alignBottom { CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX); NSDictionary *atsortingbutes = @{NSFontAtsortingbuteName : self.font}; CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSSsortingngDrawingUsesLineFragmentOrigin | NSSsortingngDrawingUsesFontLeading atsortingbutes:atsortingbutes context:nil]; int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight); int numberOfNewLined = (self.frame.size.height/self.font.lineHeight) - numberOfLines; NSMutableSsortingng *newLines = [NSMutableSsortingng ssortingng]; for(int i=0; i< numberOfNewLined; i++){ [newLines appendSsortingng:@"\n"]; } [newLines appendSsortingng:self.text]; self.text = [newLines mutableCopy]; } 

Swift 2.0:: Utilisation de l'extension UILabel

Faites des valeurs enum constantes dans un file Swift vide.

 // AppRef.swift import UIKit import Foundation enum UILabelTextPositions : Ssortingng { case VERTICAL_ALIGNMENT_TOP = "VerticalAlignmentTop" case VERTICAL_ALIGNMENT_MIDDLE = "VerticalAlignmentMiddle" case VERTICAL_ALIGNMENT_BOTTOM = "VerticalAlignmentBottom" } 

Utilisation de l'extension UILabel:

Créez une class Swift vide et nommez-la. Ajouter le suivant.

 // AppExtensions.swift import Foundation import UIKit extension UILabel{ func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : Ssortingng) -> UILabel { let rect = sampleLabel!.textRectForBounds(bounds, limitedToNumberOfLines: 0) switch positionIdentifier { case "VerticalAlignmentTop": sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y, rect.size.width, rect.size.height) break; case "VerticalAlignmentMiddle": sampleLabel!.frame = CGRectMake(bounds.origin.x+5,bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height); break; case "VerticalAlignmentBottom": sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y + (bounds.size.height - rect.size.height),rect.size.width, rect.size.height); break; default: sampleLabel!.frame = bounds; break; } return sampleLabel! } } 

Utilisation:

 myMessageLabel.makeLabelTextPosition(messageLabel, positionIdentifier: UILabelTextPositions.VERTICAL_ALIGNMENT_TOP.rawValue) 

Swift 3 version de la réponse de @ totiG

 class UIVerticalAlignLabel: UILabel { enum VerticalAlignment : Int { case VerticalAlignmentTop = 0 case VerticalAlignmentMiddle = 1 case VerticalAlignmentBottom = 2 } @IBInspectable var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop { didSet { setNeedsDisplay() } } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect { let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines) switch(verticalAlignment) { case .VerticalAlignmentTop: return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height) case .VerticalAlignmentMiddle: return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height) case .VerticalAlignmentBottom: return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height) } } override func drawText(in rect: CGRect) { let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines) super.drawText(in: r) } } 

Si ce dont vous avez besoin est un text non éditable qui commence par défaut dans le coin supérieur gauche, vous pouvez simplement utiliser une vue text au lieu d'une label, puis définir son état sur non éditable, comme ceci:

 textview.isEditable = false 

Bien plus facile que de jouer avec les labels …

À votre santé!

Si ce dont vous avez besoin est un text non éditable qui commence par défaut dans le coin supérieur gauche, vous pouvez simplement utiliser une vue text au lieu d'une label, puis définir son état sur non éditable, comme ceci:

 textview.isEditable = false 

Bien plus facile que de jouer avec les labels …

J'espère que cela aide!