如何设置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
比搞乱标签更容易
希望能帮助到你!