使用autolayout实现UITabelViewCell动态高

2016-10-21  本文已影响33人  十年祤茉

在iOS8之前我们需要动态的计算每个cell的高度,但是iOS8之后,我们就可以使用autolayout自动计算cell的高度, 把这个烦人的高度交给autolayout就行了.

原理很简单.为了更加简明的实现效果,就随便写一个小demo

首先我们看一下最终效果

最终效果

cell的样式:

cell的样式

接下来我们来设置各个控件的约束
1.设置Image约束:距屏幕上边和左边各10个像素,宽高都是45像素

Image的约束

2.设置titleLabel约束:距屏幕上边和右边各10个像素,距image右边10像素,不要给高度

titleLabel的约束

3.设置contentLabel约束:距fromLabel底部10像素,距屏幕左边和右边各10像素,

注意:因为contentLabel是最下面的控件,所以一定要设置他距cell底部的距离(只有设置这个距离之后,contentLabel高度变化时,他才会去挤压cell,使cell跟随着变大)
contentLabel的约束

当你设置玩这些,Xcode会给我们报一个错误:


Xcode报出的错误

我们点击进去按照xcode上给出的默认解决办法就好,我们的约束都没有问题,为啥会还会出现这个问题呢,这个就跟Content Hugging Priority 和 Content Compression ResIstance Priority有关了


Content Hugging Priority 其实就是阻止view变大的力量,Content Compression ResIstance Priority是阻止view变小的力量。

由于我们把titleLabel和contentLabel都设置了距离cell右边固定距离,所以他两都有可以是自身变大的力量,且优先级是1000,也就是说一旦文本内容比较多,就会向下拉伸。可是titleLabel和contentLabel都具有变大的力量,而且优先级是一样的,都是251,当出现都要变大时,xcode不知道该优先拉伸哪一个为好,所以也就抛出了错误。我们只要把contentLabel的Vertical的优先级调大一点就可以了(251->252)。或者把titleLabel的Vertical的优先级调小一点(251->250)

我们可以看一下现在运行的效果



大家有没有发现这个问题,如果标题行数为2行或者以上就没有问题,如果标题为一行话,有些内容就会把头像的下面的部分覆盖了

为什么会出现这个问题呢?这就要从设置contentLabe约束l开始说起了,我们设置contentLabel约束时候,只让它距titleLabel的底部10个像素,没有考虑到如果标题的高度比头像的高度小的情况,所以当标题高度比头像高度小的话,contentLabel会覆盖Image.

这个时候我们应该怎么设置contentLabel的约束呢?

在contentLabel原来约束的基础上,增加一个相对于Image的约束,距Image底部大于等于10像素,然后把距离titleLabel底部的距离设置为大于等于10像素,这样Image和titleLabel谁的高度更高,contentLabel就距离高度较高的底部10个像素

contentLabel调整后的约束

以上就是在xib里需要做的事情

接下来是代码里需要实现的东西:

在控制器中的 viewDidLoad的方法里只需要添加两句代码即可

- (void)viewDidLoad {
[super viewDidLoad];

// 设置数据源
_dataArray = @[@"设置的 AutoLayout 约束必须让 cell 的 contentView 知道如何自动延展。关键点是 contentView 的 4 个边都要设置连接到内容的约束,并且内容是会动态改变尺寸的并且内容是会动态改变尺寸的并且内容是会动态改变尺寸的。",@"设置连接到内容的约",@"fjdsfds",@"要设置连接到内容的约束,并且内容是会动态改变尺寸会动态改变尺会动态改变尺",@"sdfjslfff"].mutableCopy;
_titleArray = @[@"疯狂的拉萨得思考",@"标题的长度要长一点标题的长度要长一点标题的长度要长一点标题的长度要长一点标题的长度要长一点标题的长度要长一点标题的长度要长一点标题的长度要长一点",@"sla接发的是",@"反倒是范德萨发范德萨发大厦范德萨发大厦范德萨范德萨发范德萨发大厦反倒是",@"粉丝发的是拉开富家大室"].mutableCopy;

// 告诉tableView的真实高度是自动计算的,根据你的约束来计算
self.tableView.rowHeight = UITableViewAutomaticDimension; 

// 设置cell的预估行高 ,作用:在tablView显示时候,先根据估算高度得到整个tablView高,而不必知道每个cell的高度,从而达到高度方法的懒加载调用
self.tableView.estimatedRowHeight = 200; 

}

实现numberOfRowsInSection方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

return 5;
}

将cellForRowAtIndexPath方法改为如下样子

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSString *identifier = @"testcell";
    TestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"TestTableViewCell" owner:self options:nil] lastObject];
    }
    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];
    cell.title.text = _titleArray[indexPath.row];
    cell.content.text = _dataArray[indexPath.row];
    
    return cell;

}

至此我们所有的工作就完成了,大家有没有发现,我们没有一句代码去实现 heightForRowAtIndexPath 方法,但是最终的效果却实现了cell高度的自适应

下面就是最终的效果:

最终效果
上一篇 下一篇

猜你喜欢

热点阅读