在iOS开发中,用的最多的一个控件非UILabel莫属了。
之前在tableview的自定义不等高的cell时候用过cell的一些较为复杂的应用了。
在日常的开发中会发现,如果UILabel高度有多行,当内容少的时候,那么文字就会默认靠左垂直对齐,如下图:
所以我就有了将文字顶部对齐的需求: stackoverflow.com 上提供了几种方法来达到顶部对齐的效果。
方法一
在显示文字时,用sizeToFit修改Label的高度
[label sizeToFit] ;
如果内容长度超过一行,把numberOfLines设成 0(就是不限制行数)。
有一个问题是,不管你设置了文字是水平居中还是右对齐,那么执行完sizeToFit后 frame 宽度也缩小了,文字会缩到左上角,效果都比较差,如图:
方法二
此方法更加简单粗暴,但是很有效。其方法是在文本后面加多一些\n。
需要注意的是,\n后还得加至少一个空格,否则多余的\n会被UILabel忽略。从这一点上看,UILabel似乎又过于“聪明”了。是把UILabel的 “line break mode” 设为 “Clip”,然后直接在末尾加一些换行符
该方法的示意图如下:
该方法的代码如下:
label.lineBreakMode = UILineBreakModeClip;
label.text = [displayString stringByAppendingString:"\n\n\n\n"];
不过,这个方法不是万能的,当Label文字超出范围并且需要在末尾显示“…”就不行了,不会自动缩略末尾变成“…”。
方法三
用UITextField代替UILabel
用UITextField取代UILabel,默认就是顶端对齐的。
同时把userInterationEnabled设为NO,让它不能滚动。
方法四
重写UILabel的drawTextInRect:方法
创建一个UILabel的子类,用起来非常方便:
// TopLeftLabel.h
#import
@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的分类
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end
@implementation UILabel (VerticalAlign)
- (void)alignTop
{
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<= newLinesToPad; i++)
{
self.text = [self.text stringByAppendingString:@" \n"];
}
}
- (void)alignBottom
{
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i< newLinesToPad; i++)
{
self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
}
@end
调用只需用下面两行代码即可实现效果:
[myLabel alignTop];
[myLabel alignBottom];
实现
在本项目中,使用第一种方式,一句代码就解决了问题!因为撸主是使用xib来做cell,一开始写在了layoutSubviews方法中
- (void)layoutSubviews{
[super layoutSubviews];
[self.captionLabel sizeToFit];
[self.containerView clipsToCornerRadius:8];
}
但是,出现了第二次滑动到指定位置才有效,并且有奇奇怪怪的效果??
考虑到是cell的重用缓存,以及view的生命周期顺序问题:layoutSubviews方法调用先于drawRect
我要在View绘制子控件时再次确定cell的布局,于是把代码放到drawRect中:
- (void)drawRect:(CGRect)rect{
[self.captionLabel sizeToFit];
[self.containerView clipsToCornerRadius:8];
}
如果还是有问题,可以考虑直接用其他方式,如后来出现有UILabel文字显示不全的现象,最后用方法二代替了~
一起进步~共勉❤️
转载时请注明出处及相应链接,本文永久地址:https://blog.yayuanzi.com/25034.html
微信打赏
支付宝打赏
感谢您对作者Annwn的打赏,我们会更加努力! 如果您想成为作者,请点我