结合AutoLayout实践iOS8上UITableViewCell高度的自适应

上一次写博客已经是4个月之前了,不是不想写,只是没找到太合适的题目,本人秉着宁缺毋滥的原则......

好吧,我承认是我懒惰了;

四个月,虽然陆续提交了几个项目,但是所学所用变化不大;与此同时,随着公司人事比较大的动,我也重新找到了自己的位置,希望自己能百尺竿头,更进一步^_^

今天想写的,题目已经表示出来了,灵感的来源是“iOS进阶指南试读之UI篇”这篇文章,正好下午没事就实践了一下,下面就把实践的一些东西记录一下;

autolayout

最早还是自己手动写cell的时候,还是通过计算frame的方式进行UI布局,记得是iOS8出来的时候吧,正好二期项目开始,就和当时的同事一起学习了如何使用autolayout进行UI布局,因为要进行6s和6plus的适配,一开始确实有些怪,但后来慢慢也就习惯了,觉得很好用,但是对于cell的高度还是要算(其实可以自适应,后边会讲到),限于对autolayout的理解程度,一篇UI上的约束我自己看着都乱;

1. Intrinsic Content Size(借用一下标题^_^)

先举个例子吧,之前对这样一个界面

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第1张图片

之前的方式:

我会分别对三个label(1、2、3)进行 距上-距左-距右,以及高度的约束设置(注意label3没有距下的约束);然后在Controller中根据拿到的数据源进行文本显示区域高度的计算以契合该cell,最后的cell高度由其内部各视图的高度计算得出,通过tableVIew的代理再设置一下;

是不是忍不了,我也忍不了,但是没办法啊>_<,不过没关系,当你读完这篇文章的时候,也许就不用在这样做了;

autolayout:

所谓autolayout,其实就是系统通过我们所设置的约束,对UI上的相关控件进行自动布局,那么约束就显得至关重要了;

上图所示的红色View,并在上面依次放了3个label,以label1为例,若按之前的方式,距上-距左-距右,以及高度的约束设置,就可以确定这个视图的位置固定;

如果是UIView的话,只有距上-距左-距右,那么Xcode就会提示需要进行高度的设置,因为如果不进行高度的设置,这个视图的位置是无法确定的:

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第2张图片

autolayout的本质就是系统通过你设置的约束帮你计算一个控件的位置和大小;

但如果是UILabel的话,只有距上-距左-距右,那么Xcode则不会提示,即不需要进行高度约束的设置:

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第3张图片

之所以有这种情况,是因为有些视图可以通过自己的额内容计算高度,而有些视图则不可以;对应所要讲的就是我们的小标题 Intrinsic Content Size(固有内容大小);

对应的系统方法是 -(CGSize)intrinsicContentSize;

UIView&UILabel:

一个UIlabel肯定具备四个条件:内容、字体、行数、换行模式;即只要赋予了label内容,label的大小也就确定了,也因此,我们不需要特意指定一个UILabel的宽高(特殊要求除外);

UIView不可以自己计算大小,则是因为他没有内容;

Intrinsic Size-Placeholder:

那如果我们不想用label自己计算的高度,或是UIView的高度我们也不想通过添加约束的方式来设置,利用Intrinsic Size的Placeholder,我们是可以做到的;

我们先看一个例子:基于上图,我们把label的高度拉大一点,Xcode会给出一个警告,意思是 真实的高度是44,但自己计算的却不是这个值,如下图;

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第4张图片

在右侧面板显示约束的下边,存在Intrinsic Size的属性设置:

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第5张图片

我们看到默认使用系统定义的,对应的也就是现在警告的情况;

我们在xib中将Intrinsic Size属性设置为Placeholder,这样就不会报错了(如下图):

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第6张图片

这个属性的作用就是给相应视图提供一个默认的大小;

如果是代码实现的可以在UILabel的子类中,重写 -(CGSize)intrinsicContentSize;方法,如:

- (CGSize)intrinsicContentSize
{
    CGSize originalSize = [super intrinsicContentSize];

    CGSize size = CGSizeMake(originalSize.width+20, originalSize.height+20);

    return size;
}
表示:先获取系统通过label内容计算出来的大小,再分别增大返回新的Size即可;

2.Content Hugging Priority & Content Compression Resistance Priority:

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第7张图片

这两个概念需要结合我们上面讲的Intrinsic Content Size来理解,每一个控件都有一个系统计算的最佳大小:
Content Hugging Priority这个属性就代表着,一个控件拒绝本身size大于InstrinsicSize的优先级;
Content Compression Resistance,这个属性代表着,一个控件拒绝本身size小于InstrinsicSize的优先级;

优先级越高,拒绝的程度就越大,也就是最后才会被拉伸或压缩;


我们举一个例子:

1.新建一个cell,UI同这篇blog的第一张图;

2.label的约束均为:距上 距下 距左 距右(不设宽高,自动计算);

3.然后我们改变cell的宽高;

如果3个label的拉伸或压缩优先级的相同(上图中的251 750)是不被允许的,因为随着cell的宽高变化,label面临一个问题,在保持和父View间距不变的情况下,必须有一个label做出妥协,即进行宽高的变化,否则Xcode是不知道到底该拉伸哪个Label的;

那到底那个先做出妥协,这就是这两个属性的作用;


我们对label1-label2-label3做出以下优先级调整:

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第8张图片结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第9张图片结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第10张图片

即随着cell的变化,3个label是有一个变化顺序的,看看下面的图示,是不是和我们预想的一样:

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第11张图片结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第12张图片

结合AutoLayout实践iOS8上UITableViewCell高度的自适应:

在做这个Demo时,我忽然想起,许久之前看到的关于iOS8上,cell高度自适应的属性设置,那时还不甚理解,现在看来其实原理就是基于有些控件的高度自动计算反推cell的高度,那时系统也还需要满足iOS7,也就搁置了,现在的项目是基于iOS8的,接下来就让我们来操作一下:

1.新建一个cell,UI同这篇blog的第一张图;

2.label的约束均为:距上 距下 距左 距右(不设宽高,自动计算);

3.红色View的约束为:距上 距下 距左 距右;

tableView设置rowHeight为UITableViewAutomaticDimension,表示自动计算cell尺寸:

   self.tableView.estimatedRowHeight = 50.0f;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
我们再将数据源设置为不同长度的文本:

    
    [self.tableArray addObjectsFromArray:@[@{@"label1":@"auwefhauwehf",
                                             @"label2":@"auwefhauwehf",
                                             @"label3":@"auwefhauwehf"},
                                           @{@"label1":@"auwefhauwehfauwefhauwehf",
                                             @"label2":@"auwefhauwehfauwefhauwehf",
                                             @"label3":@"auwefhauwehfauwefhauwehf"},
                                           @{@"label1":@"auwefhauwehfauwefhauwehfauwefhauwehf",
                                             @"label2":@"auwefhauwehfauwefhauwehfauwefhauwehf",
                                             @"label3":@"auwefhauwehfauwefhauwehfauwefhauwehf"}]];

最后把heightForRowAtIndexPath的代理方法注释掉;

运行代码,结果如下:

结合AutoLayout实践iOS8上UITableViewCell高度的自适应_第13张图片

我们看到:

虽然我们设置的预计的RowHeight是50,但是实际显示出来的cell确实根据各个label自己计算出来的高度得出来的,而我们并没有设置任何一个label的高度约束;

当然,这多亏了iOS8提供的UITableViewAutomaticDimension;


总结:

在写这篇blog时,内心有些小激动,因为我知道,这将改变我原来对UI布局的诸多认知,也希望对大家有所帮助;

之前还在Xcode中新建了一些类的模板,很受用,再写的话就把这个写了,哈哈^_^;

感谢叶孤城___(简书作者)的iOS进阶指南试读之UI篇”,使这篇文章成为可能。



你可能感兴趣的:(iOS开发技术要点)