如何设置UILabel for iOS应用程序的左上alignment方式?

我已经在我的笔尖文件中添加了一个标签,然后需要为该标签左上angularalignment。 由于我在运行时提供文本,所以不知道有多less行。 所以如果文本只包含单行,那么它显示为垂直中心alignment。 这alignment不符合我个人在前面的标签。

例如:

在这里输入图像说明

这看起来很奇怪:(

有没有什么办法可以将标签文本设置为左上alignment?

而不是重新解释,我将链接到这个相当广泛和高度评价的问题/答案:

将文本垂直alignment到UILabel中的顶部

简短的答案是否定的,苹果公司并没有让这个简单,但它可以通过改变框架的大小。

这很容易做到。 使用verticalAlignment属性创buildUILabel sublcass,并覆盖textRectForBounds:limitedToNumberOfLines以返回顶部,中部或底部垂直alignment的正确边界。 代码如下:

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 

SOLabel为我工作。

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:

这个版本已经从原来的更新,支持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) } } 

我在StoryBoard中find了一个使用AutoLayout的解决scheme。

1)将行号设置为0,并将文本alignment设置为左侧。

在这里输入图像说明

2)设置高度限制。

在这里输入图像说明

3)高度约束应该在关系 – 小于或等于

在这里输入图像说明

4)

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

我得到的结果如下:

在这里输入图像说明

在你的代码中

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

请注意,如果您在表格单元格或其他视图中使用不同的数据进行回收,则需要将原始框架存储在某处并在调用sizeToFit之前将其重置。

我也遇到了这个问题,但是我发现你设置UILabel的属性和方法的顺序很重要!

如果您在label.font = [UIFont fontWithName:@"Helvetica" size:14];之前调用[label sizeToFit] label.font = [UIFont fontWithName:@"Helvetica" size:14]; 那么文本不会alignment顶部,但如果你交换它们,那么它呢!

我也注意到,设置文本首先也有所不同。

希望这可以帮助。

我发现了同样的问题的另一个解决scheme。 我使用UITextView而不是UILabel并将editable()函数切换为false。

在使用界面构build器时,请为您的标签设置约束(请务必设置高度和宽度)。 然后在尺寸检查器中检查标签的高度。 在那里,你会希望它读取> =而不是=。 然后在该视图控制器的实现中,将行数设置为0(也可以在IB中完成)并设置标签[label sizeToFit]; 随着文本的长度增加,标签将会高度增长,并保留文本在左上方。

SoLabel解决scheme的工作,谢谢。

贝娄我已经添加了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 } 

最简单和最简单的方法是在StackView中embeddedLabel,并将StackView的Axis设置为水平,在Storyboard的属性检查器中将其alignment到Top, 如下所示 。

对于iOS 7来说,这就是我为我制作的

 @implementation UILabel (VerticalAlign) - (void)alignTop { CGSize boundingRectSize = CGSizeMake(self.frame.size.width, CGFLOAT_MAX); NSDictionary *attributes = @{NSFontAttributeName : self.font}; CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes 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 *attributes = @{NSFontAttributeName : self.font}; CGRect labelSize = [self.text boundingRectWithSize:boundingRectSize options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil]; int numberOfLines= ceil(labelSize.size.height / self.font.lineHeight); int numberOfNewLined = (self.frame.size.height/self.font.lineHeight) - numberOfLines; NSMutableString *newLines = [NSMutableString string]; for(int i=0; i< numberOfNewLined; i++){ [newLines appendString:@"\n"]; } [newLines appendString:self.text]; self.text = [newLines mutableCopy]; } 

Swift 2.0 :使用UILabel扩展

在一个空的Swift文件中使用常量枚举值。

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

使用UILabel扩展:

做一个空的Swift类并命名它。 添加以下内容。

 // AppExtensions.swift import Foundation import UIKit extension UILabel{ func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) -> 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! } } 

用法:

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

swift 3版本的@ 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) } } 

如果您需要的是默认情况下从左上angular开始的不可编辑文本,则可以简单地使用文本视图而不是标签,然后将其状态设置为不可编辑,如下所示:

 textview.isEditable = false 

比搞乱标签更容易

干杯!

如果您需要的是默认情况下从左上angular开始的不可编辑文本,则可以简单地使用文本视图而不是标签,然后将其状态设置为不可编辑,如下所示:

 textview.isEditable = false 

比搞乱标签更容易

希望能帮助到你!