iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)

需求

使用过UILabel,会发现UILabel可以设置三种对齐方式,靠左,居中,靠右。满心欢喜地以为原来就这么回事,苹果都帮我们做好了呀。

可是,接到一个需求是使文字在cell的子控件UILabel中文字吸顶,找了半天都没有这样的属性..

iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第1张图片

设置了UILabel的高度>=60,Lines=0,于是乎实现出来的效果是酱紫的:
iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第2张图片

产品并不买账,说了吸顶就是要吸顶哦,看起来美观一点~
苹果爸爸也没有那么体贴啊这个都不帮我们做…
这个时候只能靠聪慧的大(Stack)脑(Overflow)了。


解决办法

经过苦苦搜寻,发现了几个解决办法哦,点击这里可以看原文!

原文撸主的需求和我很像,要在两行的UILabel中实现吸顶。
iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第3张图片

热心的网友给出了解决办法,其中有五个是比较好使的,大家可以根据需求自己采用哈!

1)用sizeToFit修改Label的高度

没法直接改变UILabel的垂直对齐方式(UILabel没有这个属性),但是把 label 的 frame 高度改小也能实现相同的效果。

为了看得清楚,把 label 背景标为橘黄色,如图:
iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第4张图片

如果内容长度超过一行,把numberOfLines设成 0(就是不限制行数)。

有一个问题是,不管你设置了文字是水平居中还是右对齐,那么执行完sizeToFit后 frame 宽度也缩小了,文字会缩到左上角,效果都比较差,如图:
iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第5张图片

解决方法是把 label 的宽度先用变量保存起来,执行完sizeToFit之后再设回来,就解决了上面的问题,如图:
iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第6张图片

另外要注意,sizeToFit 会把 label 的当前宽度当做最大宽度,执行之后宽度只会比变窄,不会变宽。
iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第7张图片

Last but not least! 如果你是使用Auto Layout 的 NIB 和 Storyboard,Mark Amery 在评论中补充了解决方案:

如果 nib 或 storyboard 里用了 autoLayout,那么在viewDidLoad调sizeToFit是不管用的,因为实际顺序是先执行viewDidLoad再执行 autoLayout,执行 autoLayout 的时候会把 sizeToFit 的结果覆盖掉。
不过,在viewDidLayoutSubviews里调sizeToFit是管用的。

2)末尾补充换行符”\n”

一个更简单粗暴的办法,是把UILabel的 “line break mode” 设为 “Clip”,然后直接在末尾加一些换行符。

myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];

不过,这个方法不是万能的,当Label文字超出范围并且需要在末尾显示“…”就不行了,不会自动缩略末尾变成“…”。

3)用UITextField代替UILabel

用UITextField取代UILabel,默认就是顶端对齐的。
同时把userInterationEnabled设为NO,让它不能滚动。

4)重写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

5)自定义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];
}

但是,出现了第二次滑动到指定位置才有效,并且有奇奇怪怪的效果:
iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第8张图片
考虑到是cell的重用缓存,以及view的生命周期顺序问题:layoutSubviews方法调用先于drawRect
我要在View绘制子控件时再次确定cell的布局,于是把代码放到drawRect中:

- (void)drawRect:(CGRect)rect{
    [self.captionLabel sizeToFit];
    [self.containerView clipsToCornerRadius:8];
}

iOS开发技巧 - 使UILabel中的文字吸顶(顶部对齐)_第9张图片

如果还是有问题,可以考虑直接用其他方式,如后来出现有UILabel文字显示不全的现象,最后用方法二代替了~

你可能感兴趣的:(iOS开发,ObjectiveC)