AutoLayout处理UITableView动态高度
我们经常会遇到UITableViewCell的高度要跟随内容而调整,在未引入AutoLayout之前,我们使用以下方法计算Label高度,然后heightForRowAtIndexPath中返回计算的高度,这种做法,真的很土很局限很不好,如果UILabel使用了CoreText或者UIKit进行了富文本不同字体的排版,它更是没办法,我还得分段来计算,总之各种麻烦。
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode NS_DEPRECATED_IOS(2_0, 7_0, "Use -boundingRectWithSize:options:attributes:context:"); // NSTextAlignment is not needed to determine size
本系列文章我们讨论的是AutoLayout,那iOS6引入AutoLayout之后,情况是否有所变化呢?当然!而且AutoLayout在iOS不断更新过程中,也在一起不断的优化,以方便开发者进行布局。说实话,跟很多开发者一样,我目前也并不是特别喜欢AutoLayout,有一些不可控的因素,布局并没有完全掌握在自己手上,需要依赖系统根据约束进行调整,这让保守的开发人员很没有安全感。不废话了,我们还是进入到正题。
我们直接拿一个现实的需求来进行讨论,如下图,我们需要构建一个页面,上面部分显示我们预约保养的基本信息,下面部分显示该门店目前提供的优惠券列表,这种需求最简单的做法就是直接用两种UITableViewCell,下面的部分的UITableViewCell要简单一些,高度固定,而上面部分的UITableViewCell的内容有很多不确定的内容,比如用户预约保养选择的项目,门店的名称地址,这些UILabel的高度都不确定,所以导致上面部分的UITableViewCell的高度需要动态调整,这是一个比较典型的实例,我们一起来看一下如何解决。
一、建立合理的约束
我们先建立自定义Cell: AppointmentedInfoCell (创建XIB)。 然后设置合理的约束条件,什么是合理的约束条件,一方面我们需要按前面讲到的设置正确的约束条件,另一方面我的意思主要是控件的compression resistance 和 hugging constraints ,在IB中如下图:
我们知道在Autolayout中,我们的UILabel,UIButton等控件都有了内建大小(intrinsic content size),就是说控件的大小会根据内容进行自动调整,可以将这些控件的大小和ScrollView的bounds和contentSize进行对比,意思有点类似,只不过UILabel,UIButton这些控件并不像Scrollview一样可以在bounds不等于contentSize的情况下进行滚动查看内容。 在这里为了使用UILabel的内建大小,我们要保持compression resistance 和 hugging constraints 的垂直方向优先级没有被更高的优先级所覆盖,比如更改了UILabel内建大小的优先级(priority),并设置了UILabel的高度约束的优先级高于内建大小的优先级,那内建大小自然就不起作用了,就会以高优先级为准.
一方面我们确保了AppointmentedInfoCell中的控件,目前全是UILabel,其内建大小垂直方向优先级为最高的1000。 光这个还不够,我们还要确保内建大小的边缘跟随内建大小一起变化,从而保证我们的内建大小可以起作用,说白了,就是要求contentView中的子控件建立与superView的约束,我们先建立第一个UILabel(姓名、电话)与superview top 的间距约束,然后依次往下建立控件之间推荐间距的约束,左边同列控件建立左部对齐约束,右边同行内容的建立顶部对齐约束,垂直方向的间距约束,最底部的”预约结果Label”建立与superview bottom的间距约束。
特别提醒:与contentView的四边间距约束很重要,有了4个与contentView的边缘约束,才能保证contentView的大小跟随其subviews变化。
上面这些就是建立合理的约束条件,这里随便提醒一下,UILabel在IB中布局的大小如果跟内容计算出来的不一致就会有警告,比如UILabel长度为200,目前的内容为2个14号字的长度,那UILabel就会有警告,对于这种警告,你需要忍住你的强迫症。
二、计算行高
这一步在iOS7与iOS8上面就有所不同了,我们先来看最新的iOS8。
1、iOS8:
从iOS8开始引入了UITableViewCell的高度的自适应功能,在iOS8之前实现很麻烦的功能,iOS8以后就不需要自己动手去做了,稍后我们会看一下iOS7下面如何做。
//打开tableview的高度估算功能
_iTableView.rowHeight = UITableViewAutomaticDimension;
_iTableView.estimatedRowHeight = 70.0;
estimatedRowHeight必须设置为大于0,为了画面的过度顺畅,保证UITableview的高度变化不至于导致UITableview的大范围滚动而影响了用户视觉体验,我们用一个预估的平均值,这也就是所谓的预估值。estimatedRowHeight并不是最终的行高,当一个Cell需要显示的时候,会精确计算实际的行高,contentView的宽度就是UITableview的宽度减去Section Index,accessoryView等的宽度,contentView的高度则会自动根据其子视图的约束关系计算,当此精确值被计算出过后,estimatedRowHeight、tableview的contentSize,bounds,这些都会跟随更新。
estimatedRowHeight每一行都会使用此值用于该行的预估值,进而初步预估UITableView的contentSize。如果UITableView每行内容变化很大,行高差别很大,那我们可以使用以下方法为每一行设置各不相同的预估值。也就是说有通用值,也有个性值。
- (void)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;
OK,预估值只是一个插曲,我们来看精确值,在iOS8过后,我们只需简单的激活预估值,并在heightForRowAtIndexPath中返回UITableViewAutomaticDimension即可。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (IS_IOS8_OR_ABOVE) {
return UITableViewAutomaticDimension;
}
}
2、iOS7:
UITableViewCell的contentView的高度自适应是iOS8中加入的,iOS7就只能自己计算了,所以我们来看一下iOS7下如何处理的。
//NIB注册,获取自定义UITableView实例的方式有很多种,这里随便用一种
UINib *cellNib = [UINib nibWithNibName:@"AppointmentedInfoCell" bundle:nil];
[self.tableView registerNib:cellNib forCellReuseIdentifier:@"AppointmentedInfoCell"]; //先创建一个基本的Cell实例,我们后面cellForRowAtIndexPath 和 heightForRowAtIndexPath 都需要用,由于UITableView的加载过程是先计算出所有的行高,再对每行进行渲染的,即 heightForRowAtIndexPath是先调用的,所以这里的baseCell就是一个离屏控件,用于辅助计算高度的,而后面也可以直接使用其用于每行内容的更新,每种类型的Cell只需要一个即可,这样我们的离屏内存并不会浪费。 _baseCell = [cellNib instantiateWithOwner:nil options:nil][]; //更新Cell内容
- (void)configureCell:(AppointmentedInfoCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
//更新contentView的子控件
} //
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
AppointmentedInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AppointmentedInfoCell" forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
} //
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
[self configureCell:_baseCell atIndexPath:indexPath];
[_baseCell layoutSubviews];
CGFloat height = [_baseCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height + ;//由于分割线,所以contentView的高度要小于row 一个像素。
}
OK,到这里,我们基本上就掌握了AutoLayout的UITableViewCell的动态高度的处理,关键点就是systemLayoutSizeFittingSize的使用,希望本篇能够帮助你更好的理解AutoLayout以及UITableView在iOS8新增的布局处理。
AutoLayout处理UITableView动态高度的更多相关文章
- AutoLayout深入浅出五[UITableView动态高度]
本文转载至 http://grayluo.github.io//WeiFocusIo/autolayout/2015/02/01/autolayout5/ 我们经常会遇到UITableViewCell ...
- 使用Autolayout xib实现动态高度的TableViewCell
http://my.oschina.net/u/2360693/blog/481236?p={{totalPage}} 创建Xib文件 首先将Cell做好布局,调整到满意的位置和宽度,然后开始做Aut ...
- iOS开发——使用Autolayout生成动态高度的TableViewCell单元格
步骤一.TableViewCell中使用Autolayout 要点:Cell的高度必须在Constraints中指明,但不能定死,需要让内部由内容决定高度的View决定动态高度. 如UILabel设置 ...
- swift 版本 UItableViewCell的动态高度补足
用swift的朋友们很多都是从ios8开发了, 其中针对table cell高度自动计算的 UITableViewAutomaticDimension 异常好用,但好像只对uilabel对象有效 ...
- soui中,列表控件动态高度的使用注意
1.listview的模板template中,需要增加defHeight属性,即默认高度,同时,不能出现itemHeight属性,否则动态高度会失效 2.数据适配器中,重写getViewDesired ...
- UITableView动态存放、重用机制
一.UITableView动态存放 #import "ViewController.h"@interface ViewController ()<UITableViewDel ...
- css中height 100vh的应用场景,动态高度百分比布局,浏览器视区大小单位
css中height 100vh的应用场景,动态高度百分比布局,浏览器视区大小单位 height:100vh 一些只能vw, vh才能完成的应用场景: 1. 场景之:元素的尺寸限制 vw vh 主要是 ...
- 精简计算UITableView文本高度
精简计算UITableView文本高度 本人视频教程系类 iOS中CALayer的使用 最终效果: 核心源码(计算文本高度的类) NSString+StringHeight.h 与 NSStrin ...
- autoHeight # 动态高度添加 用 window.addEventListener('resize', function () {
动态高度添加 用 window.addEventListener('resize', function () { mounted () { this.init() window.addEventLis ...
随机推荐
- linux 查看系统版本号(转)
一.查看Linux内核版本命令(两种方法): 1.cat /proc/version [root@localhost ~]# cat /proc/versionLinux version 2.6.18 ...
- Django之用户认证—auth模块
用户认知———auth模块 目录: auth模块 User对象 实例 扩展默认的auth_user表 - 创建超级用户 - python3 manager.py createsuperuser - 认 ...
- Codeforces 163C(实数环上的差分计数)
要点 都在注释里了 #include <cstdio> #include <cstring> #include <iostream> #include <al ...
- 2019湘潭校赛 G(并查集)
要点 题目传送 题目本质是每个点必属于两个集合中的一个,伴随的性质是:如果一个人说别人true,则他们一定属于同一阵营:如果说别人fake,一定不属于同一阵营. 每个点拆为\(i\)和\(i + n\ ...
- hdu4570-区间dp
这道题的题意不是一般的难懂啊,各种查字典都没理解,还是没忍住去看了别人的博客,没想到题很简单,1-n内划分若干个区间,使的每个区间和最小,每个区间的区间和是:区间开头的数*2^区间长度. 区间dp # ...
- hibernate Restrictions用法 HibernateTemplate Hibernate结合spring
常用方法 http://www.jb51.net/article/41541.htm ........................................... 博客分类: Hiberna ...
- E. Mike and Foam 容斥原理
http://codeforces.com/problemset/problem/548/E 这题是询问id,如果这个id不在,就插入这个id,然后求a[id1] , a[id2]互质的对数. 询问 ...
- 开源项目android-uitableview介绍
在iOS应用中,UITableView应该是使用率最高的视图之一了.iPod.时钟.日历.备忘录.Mail.天气.照片.电话.短信. Safari.App Store.iTunes.Game Cent ...
- dubbo服务降级(2)
dubbo降级服务 使用dubbo在进行服务调用时,可能由于各种原因(服务器宕机/网络超时/并发数太高等),调用中就会出现RpcException,调用失败. 服务降级就是指在由于非业务异常导致的服务 ...
- ABAP事件分类
1.报表事件 INITIALIZATION. START-OF-SELECTION. END-OF-SELECTION. 2.选择屏幕事件 在INITIALIZATION和START-OF-SELEC ...