Apple 算是最重视应用开发体验的公司了.从Xib到StoryBoard,从Auto Layout到Size Class,每一次的更新,都会给iOS应用的开发带来不小的便利.但是,对于绝对多数iOS攻城狮来说,我们依然还是很害怕写UITabelVIew的自适应布局.当然,害怕不是因为我们不会写,或者本身有什么特殊的技术点,而是因为太麻烦.当然,文章的后半部分,会给出相应的解决方案,毕竟本文不是为了吐槽而吐槽.

UITabelView的自适应布局有多麻烦?

数据类型的不确定性:种类越多,页面越复杂.

以网易新闻的客户端为例,可能的数据包括文字新闻,图片新闻,图集,推广,视频等.每一种数据,又根据来源或点击量等细分出许多不同的状态.基本上每种数据类型,都至少需要一种单独的Cell去呈现,每一个Cell的布局,都要单独去写.所以说,数据的类型将直接决定页面本身的复杂度.

数据长度的不确定性: 不确定字段越多,迭代成本越高.

上图取自新浪微博.稍微有点经验的iOS攻城狮,都猜到我要吐槽什么了吧!没错,就是同种数据类型,但是内部字段的长度可能不同,而且还要都要给他们显示出来!其实我也很希望自家的应用都像网易那样,固定长度显示新闻,显示不完,就直接截断--可惜那样的应用都是别人公司的应用.可能你会说: 顶部给个非微博正文区域给个固定高度;文字区域动态计算出高度;图片部分,图片高度固定,根据数量动态计算高度;转发部分同理;然后根据数据在tabelView的代理方法tableView:heightForRowAtIndexPath: 中动态返回高度即可.是的,思路就是这么个思路,但是你确定产品经理一直不会改需求?你确定不需要适配 6plus时,字号要大点?你确定自己的应用不希望大屏上一样能显示更多的图片?你确定老板不是盘算着 iPad版也交给你维护?所以说,对于这种数据长度不确定,但是又要求完全显示的设计,最复杂的不在于实现,而在于后期的迭代.可变字段越多,迭代越复杂.如果连显示方式都改了,那就基本等于重做了几遍.

cell高度计算有坑: 难以理解的诡异问题

在 tableView:heightForRowAtIndexPath: 中计算高度时,是有坑的,对于刚接触iOS的攻城狮来说,几乎是难以理解的诡异问题.这里简单说两个,其他的大家可跟帖补充:

1.文字高度计算时 0.1 高度误差问题.

cell中经常需要使用 textRectForBounds: limitedToNumberOfLines: 来计算某一个文字的显示高度.这里,其实有一个很大的坑的,如果你没遇到只能说明你很幸运.由于浮点数四舍五入机制的存在,所以偶现UILabel最后一行无法显示的情况.原因也很诡异: 在你计算时,部分值会存在稍许的不超过0.01的误差,大多数情况下,这个误差值,可以安全忽略,但是确实存在那0.01误差刚好是绝对换行与不换行的分界值,因为0.01的误差,可能计算出来的高度就不足以显示最后几个文字.为了安全起见,如果需要计算文本高度,我都是加上一个额外的0.1来保证最后一行肯定可以显示.

2.手动调用 tableView:cellForRowAtIndexPath: 获取cell,引起的卡顿问题.

这个可能也是一些有经验的开发者也会混淆的问题: 不要在自己的代码中调用 tableView:cellForRowAtIndexPath: 方法来获取某一个位置的 cell,来进行关于这个cell的某些计算,因为你手动调用这个方法产生的cell不会参与cell的复用! 各种缘由,不过多解释,总之结论就是,只要系统自己调用tableView:cellForRowAtIndexPath: 方法产生的 cell才会参与cell的复用.
关于这个话题,比较易犯的错误是,竟然有开发者在

tableView:heightForRowAtIndexPath: 中调用 tableView:cellForRowAtIndexPath: 来获取cell,然后计算cell高度.然后你会发现,凡是稍微涉及到图片显示的界面,你的显示是对的,但是滚动非常卡顿,因为你在自己浑然不觉的情况下创建了N个Cell,而且这些Cell绝对不会参与复用.

为什么我现在不再害怕写UITabelView的自适应布局?

是的,我现在一点也不担心去处理各种UITabelView布局.不是因为我有一股所谓的不畏艰难的伟大工作精神,而是因为我切实找到了解决办法.具体该怎么做呢?

1.使用AutoLayout 布局你的cell

坦白说,咱都是刚入行的人,使用AutoLayout布局,写一个自适应的Cell,大家估计也都会.可以用xib,也可以用纯代码写.如果准备用纯代码写,建议你先好好研究下Masonry — 使用纯代码进行iOS应用的autolayout自适应布局

2.使用 UITableView-FDTemplateLayoutCell 根据单元格内容的约束自适应单元格高度

坦白说,我原来也是: 虽然cell用着AutoLayout,但是计算cell高度时,也是看着设计图返回一个适合的值--想想都虐心.前天,一个热心的开发者在我博客留言说: 他用 Masonry 进行Cell的高度自适应时遇到了问题.我第一反应是: Masonry 能用来计算cell高度?! 然后,他提到了一个第三方UITableView-FDTemplateLayoutCell,好像是国内的大神写的,具体介绍可以看这里: 优化UITableViewCell高度计算的那些事.这篇文章的博主关于 UITableView-FDTemplateLayoutCell 分析很详尽,用一句总结就是: 一行代码解决cell高度动态计算问题.

3.一个关于Masonry 和 UITableView-FDTemplateLayoutCell结合使用的小例子

示例下载地址: 点击下载

非常感谢 @未来帅哥 的讨论,给了我很大启发和帮助,我也如约做了一个关于Masonry 和 UITableView-FDTemplateLayoutCell结合使用的小例子,以解决他的问题:关于如何让左侧图片底部总是不被遮盖.

核心代码片段:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ CGFloat height = [tableView fd_heightForCellWithIdentifier: NSStringFromClass([YFAutoLayoutCell class]) cacheByIndexPath:indexPath configuration:^(YFAutoLayoutCell * cell) {
YFAutoLayoutCellModel * model = [self.data objectAtIndex: indexPath.row]; cell.model = model;
}]; return height;
}

/**
* 初始化视图.
*/
- (void) setupView
{
self.imgView = [[UIImageView alloc] init];
self.introLabel = [[UILabel alloc] init]; [self.contentView addSubview: self.imgView];
[self.contentView addSubview: self.introLabel]; self.introLabel.numberOfLines = 0; [self.imgView makeConstraints:^(MASConstraintMaker *make) {
make.top.left.equalTo(8);
make.size.equalTo(CGSizeMake(60, 60));
make.bottom.lessThanOrEqualTo(-8); // 这里是关键
}]; [self.introLabel makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.imgView.right).offset(8);
make.top.equalTo(self.imgView);
make.right.equalTo(-8);
make.bottom.equalTo(-8);
}];
}

小结

有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?因为你还在用传统的方式去计算cell的高度! Auto Layout + UITableView-FDTemplateLayoutCell + Masonry,耐心研究几个小时,绝对让你受益匪浅!

作者:iOS122

 原文地址:http://www.cnblogs.com/ios122/p/4832859.html#3272858
 

【转】有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?的更多相关文章

  1. 有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?

    本文转载至 http://www.cnblogs.com/ios122/p/4832859.html Apple 算是最重视应用开发体验的公司了.从Xib到StoryBoard,从Auto Layou ...

  2. 【转】使用 Auto Layout 的典型痛点和技巧

    layoutIfNeeded()强制立刻更新布局 原文网址:http://www.jianshu.com/p/0f031606e5f2 官方文档:Auto Layout Guide 加上去年WWDC上 ...

  3. iOS屏幕适配方案-Auto Layout

    市场上的android手机五花八门.各种尺寸的屏幕让android程序员们比較头疼. 也有一些大神写了一些博客提出了自己的观点.iOS貌似也迎来了大屏6+,因此屏幕适配的问题也是有滴,因此苹果也有自己 ...

  4. [Android开发学iOS系列] Auto Layout

    [Android开发学iOS系列] Auto Layout 内容: 介绍什么是Auto Layout. 基本使用方法 在代码中写约束的方法 Auto Layout的原理 尺寸和优先级 Auto Lay ...

  5. 【Auto Layout】Xcode6及以上版本,创建Auto Layout 约束时产生的一些变化【iOS开发教程】

    [#Auto Layout#]Xcode6创建Auto Layout 约束时产生的一些变化     通过两个小Demo来展示下变化: Demo1需求: 为控制器的根视图(图中的“控制器View”)的子 ...

  6. iOS 8 Auto Layout界面自动布局系列2-使用Xcode的Interface Builder添加布局约束

    http://blog.csdn.net/pucker/article/details/41843511 上一篇文章<iOS 8界面自动布局系列-1>简要介绍了iOS界面布局方式的前世今生 ...

  7. 手写代码自动实现自动布局,即Auto Layout的使用

    手写代码自动实现自动布局,即Auto Layout的使用,有需要的朋友可以参考下. 这里要注意几点: 对子视图的约束,若是基于父视图,要通过父视图去添加约束. 对子视图进行自动布局调整,首先对UIVi ...

  8. Auto Layout

    Auto Layout XCode5+ Auto Layout Concepts 核心的概念是约束. Constraint Basics Constant value Relation Priorit ...

  9. 使用Auto Layout中的VFL(Visual format language)--代码实现自动布局【转】

    本文将通过简单的UI来说明如何用VFL来实现自动布局.在自动布局的时候避免不了使用代码来加以优化以及根据内容来实现不同的UI. 一:API介绍 NSLayoutConstraint API 1 2 3 ...

随机推荐

  1. HDU 1242 rescue (优先队列模板题)

    Rescue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  2. vim note (1)

    'vim' go into the vim mode 'i' 'a' 's'    is means insert mode 'v' is means visual mode 'esc' is mea ...

  3. javascript参数arguments对象

    ECMAScript函数的参数与大多树其他语言中函数的参数有所不同.ECMAScript函数不介意传递进来多少个参数,也不在乎传进来参数是什么类型.函数体是通过arguments对象来访问参数数组.a ...

  4. csu1116 Kingdoms 最小生成树-枚举状态

    题目链接: csu 1116 题意: 有一幅双向图连接N个城市(标号1~n,1表示首都)  每一个城市有一个价值W. 地震摧毁了全部道路,现给出可修复的m条道路并给出修复每条道路所需的费用 问在总费用 ...

  5. 百度ai 基于node 语音识别 音频文件类型转换

    百度ai 基于node 语音识别 音频文件类型转换 项目简介 源代码移步:https://github.com/xuess/ai-baidu-node 本项目主要功能为,本地音频语音识别和文件类型转换 ...

  6. 初识Restful(学习笔记)

    什么是Restful? REST -- Resource Representational State Transfer(表现层状态转移) 本质上是一种优雅的URL表达方式,描述资源的状态和状态的转移 ...

  7. 常用到的JS 验证(包括例子)

    //验证是否为空    function check_blank(obj, obj_name){         if(obj.value != ''){                  retur ...

  8. 为什么java web项目中要使用spring

    1 不使用spring的理由 spring太复杂,不利于调试. spring太复杂,不利于全面掌控代码. spring加载bean太慢. 等等. 2 对不使用spring理由的辩驳 spring io ...

  9. python 目录下的__init__.py

    1 一个目录要成为一个package必须有__init__.py文件 The __init__.py files are required to make Python treat the direc ...

  10. pyenv 安装本地版本

    最近在用pyenv安装python的时候发现官网特别慢,经常出现拒绝访问的情况.看了一些解决方法,发现可以使用本地的python源码进行安装,让pyenv从本地下载就可以了~步骤如下: 首先从官网下载 ...