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 ...
随机推荐
- 一些我推荐的和想上的网络课程(Coursera, edX, Udacity)
从面向找工作的角度出发,我觉得以下课程有很大帮助: 首推Robert Sedgewick,也是我觉得对我帮助最大的老师,讲课特点是能把复杂的算法讲解清楚(典型例子:红黑树,KMP算法) 他在Cours ...
- 【微信小程序】开发实战 之 「数据缓存API」解析
每个小程序都可以有自己的本地缓存,可以通过 数据缓存的API 实现对本地缓存进行 设置.获取和清理.本地缓存最大为10M.localStorage是永久存储的,但我们不建议将关键信息都放在localS ...
- Whatweb网站指纹信息收集工具
常规扫描:whatweb www.baidu.com 批量扫描: whatweb -i /root/12.txt 详细回显扫描:whatweb -v www.baidu.com 加强扫描强度:what ...
- vue中的导航守卫
官方文档地址: 导航守卫:https://router.vuejs.org/zh-cn/advanced/navigation-guards.html 好的,重点内容 router.beforeEac ...
- Eclipse Photon 小技巧(tips)
本文内容: Eclipse 4.8版本 代号 photon 光量子 ,感觉更像ide了,虽然这些技巧广为认知,但是作为eclipse来说,也是很重要的. Code completion allows ...
- Consul实现服务治理
.NET Core微服务之基于Consul实现服务治理 https://www.cnblogs.com/edisonchou/p/9124985.html 一.Consul基础介绍 Consul是Ha ...
- LWIP应用指南学习。
一 TCP接口函数:tcp_init() 必须在调用其它TCP函数之前调用,必须用一个硬件定时器来配置每TCP_FAST_INTERVAL (ms)调用一次tcp_fasttmr() :每TCP_SL ...
- [RDL]中多行组列组占比报表制作
结果如下: 生意额占比表达式:=iif(Fields!生意额.Value is nothing,"",Fields!生意额.Value/sum(Fields!生意额.Value, ...
- jdk1.6与jdk1.7list集合排序区别与算法
源码分析: 在Collections.sort中: public static <T extends Comparable<? super T>> void sort(L ...
- 8.html表格相关的标记9.html表格实战《简单的网页布局》
<html> <head> <title>第八课标题表格</title> <meta charset="utf-8"> ...