我有一个UILabel,它有两行文字的空间。有时,当文本太短时,此文本会显示在标签的垂直中心。
如何垂直对齐文本,使其始终位于UILabel的顶部?
我有一个UILabel,它有两行文字的空间。有时,当文本太短时,此文本会显示在标签的垂直中心。
如何垂直对齐文本,使其始终位于UILabel的顶部?
当前回答
创建UILabel的子类。就像一个魅力:
// 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
正如这里所讨论的。
其他回答
您可以通过代码或简单地在故事板上执行以下操作来解决此问题:
将UILabel的行数设置为0。将UILabel嵌入UIView中。设置UIView约束(顶部、右侧、左侧和底部),以占用UILabel应增长到的最大空间。然后将UILabel设置为UIView的顶部、右侧和左侧,并将约束设置为底部,距离>=0。
一种更快(更脏)的方法是将UILabel的换行模式设置为“Clip”并添加固定数量的换行符。
myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];
这种解决方案不适用于所有人——特别是,如果您仍然希望在字符串末尾显示“…”,如果它超过了您要显示的行数,则需要使用较长的代码段之一——但在很多情况下,这将满足您的需要。
这个问题的简单解决方案。。。
在标签下方放置UIStackView。
然后使用“自动布局”将标签的垂直间距设置为零,并将标签的顶部约束为之前的底部。标签不会增长,stackView会增长。我喜欢的是堆栈视图是非渲染的。所以它并没有真正浪费渲染时间。即使它进行自动布局计算。
你可能需要玩“拥抱内容”和“抵抗”,但这也很简单。
我时不时地搜索这个问题,然后回到这里。这一次我有一个我认为最简单的想法,我不认为这是糟糕的表现。我必须说,我只是在使用自动布局,并不想麻烦计算帧。那只是。。。讨厌。
我也在研究这个特定的问题,所以我采纳了D.S.和nevan king的想法,并将它们基本上组合成一个子类,该子类实现了垂直对齐属性,这也允许您不止一次地更改对齐。它借用了UIControlContentVerticalAlignment类型,还支持UIControlContent垂直对齐填充。
从我所看到的情况来看,numberOfLines在垂直对齐方面似乎毫无用处,因此在这个子类中,当应用垂直对齐时,它总是设置为0。此外,如果您需要多行文本标签,您仍然需要自己设置lineBreakMode。
这就是:GitHub上的QALabel
我知道这是一篇旧文章,但垂直对齐文本是一个巨大的问题(至少对我来说是这样),我想我应该分享这个解决方案,因为我自己找不到。
在我看来,使用drawRect有点贵。使UILabel垂直对齐的正确方法是不使用UILabel。使用UITextView(多行UITextField)并观察内容属性,如下所示:
- (UITextView*)textView{
if(!_textView){
UIEdgeInsets insets = UIEdgeInsetsMake(0, 50, 0, 5);
CGRect frame = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
_textView = [[UITextView alloc]initWithFrame:UIEdgeInsetsInsetRect(frame, insets)];
_textView.delegate = self;
_textView.scrollEnabled = YES;
_textView.bounces = YES;
_textView.backgroundColor = [UIColor whiteColor];
[_textView setUserInteractionEnabled:NO];
[_textView addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
}
return _textView;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change: (NSDictionary *)change context:(void *)context {
UITextView *tv = object;
CGFloat height = [tv bounds].size.height;
CGFloat contentheight;
#ifdef __IPHONE_7_0
contentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height;
#else
contentheight = [tv contentSize].height;
#endif
switch(self.verticalAlignment) {
case VerticalAlignmentBottom:{
CGFloat topCorrect = ([tv bounds].size.height - contentheight);
topCorrect = (topCorrect <0.0 ? 0.0 : topCorrect);
tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
}
break;
case VerticalAlignmentMiddle:{
CGFloat topCorrect = (height - contentheight * [tv zoomScale])/2.0;
topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
}
break;
case VerticalAlignmentTop:{
tv.contentOffset = (CGPoint){.x = 0, .y = 0 };
}
break;
default:
break;
}
}
基本上,这里发生的是我们将我们所处的类设置为观察者,使用NSKeyValueObservingOptionNew选项查看contentSize属性,因此每次内容更改时,都会调用-(void)observeValueForKeyPath:ofObject:change:context:,然后您可以计算偏移量大小以适当对齐文本。
我不能把这归功于此,最初的想法来自这里。但是,该解决方案在iOS7上不起作用。在SO周围转了几个小时后,我发现了这个:iOS 7垂直对齐修复。其中的关键行是contentheight=[tv sizeThatFits:CGSizeMake(tv.frame.size.width,FLT_MAX)].height;。由于某种原因,在iOS 7中,获取contentSize高度不起作用,但这可以解决问题。这两个解决方案都不能单独工作,但经过一点修改后,我能够将上述解决方案合成在一起。