Table View Cell 自适应速成大法
rlbe1532
8年前
<p>纵观近几年,有太多培训机构当搅屎棍进来瞎掺和贵国的全民创业,伪造简历不说,那帮菜鸟的技术真的是辣眼睛,卧槽,好像跑偏了,今天不是来申讨培训党的,我们是正经教程,还是回到主路继续开车~~~</p> <p>此教程特地针对Xcode8,iOS10和Swift 3优化并完善,那么你需要使用Xode8或者更新的版本,并且需要你有AutoLayout,TableView以及Swift 3的相关知识。</p> <h2>I have a Table, I have a View, hing ~ , TableView</h2> <p>不管是老司机还是新司机,日常开发中使用 UITableView 来搭建应用框架的肯定都遇到过这种尴尬:辣就是在刚入门iOS开发,相信绝大部分人针对接到产品狗要做动态列表或者有动态高度的列表需求时抽出过皮带,因为那会儿主要都是手动计算,这种需求不仅费时费力,最后bug还多的一逼。</p> <p>其实这种需求涉及到的技术最主要的无非就是Cell的自适应,俗话说的好,只要你掌握了 TableView ,大部分应用你是手到擒来的,对于TableView的基础用法和复用早在12年就烂大街了,对于Cell自适应也都是老生常谈,之所以还搞这种教程,完全是看着群里一帮傻屌每天都在无下限的讨论一些恬不知耻的话题,Cell自适应就是重灾区。对于网上的教程也好,开源库也好,已经掌握的就赶紧滚犊子,不要浪费时间了。。。</p> <h2>开始吧</h2> <p>在乔帮主时代,那是的确没办法,基本上都是通过手动计算 Label 和各种可变动控件的高度,而且要是考虑屏幕旋转,那就头大咯,还好那会儿屏幕没有太多尺寸。</p> <p>步入库克时代,大概苹果的工程师也觉得手动计算麻烦的一逼,于是有了 AutoLayout 以及开放了新的Api。</p> <p>Objective-C:</p> <pre> <code class="language-objectivec">- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize; </code></pre> <p>Swift:</p> <pre> <code class="language-objectivec">funcsystemLayoutSizeFitting(_targetSize: CGSize) -> CGSize </code></pre> <p>利用此Api,无论你是代码党还是煞笔党,配合 AutoLayout 就可以搞定Cell自适应的问题,可以说是载歌载舞啊。</p> <p>现在,得益于 iOS8 对 Interface Builder 改进和 AutoLayout 的优化,只要是你的应用适配到 iOS8 以上,解决Cell自适应的问题那就So Easy!!!</p> <p>那么接下来你需要搞定如下几个简单步骤:</p> <ul> <li>使用 AutoLayout 创建你的TableView。</li> <li>把 rowHeight 设置成 UITableViewAutomaticDimension 。</li> <li>利用 estimatedRowHeight 设置一个预估高度或者自行实现预估高度的代理方法。</li> </ul> <p>你先别逼逼问为什么要这么做,这是速成大法,先给你看效果才是最重要的,跟着做就行了,做完不懂再逼逼。。。</p> <h2>姿势One:接需求</h2> <p>假设你有个煞笔客户,要让你做一个艺术家作品展示的应用,那么进入应用的第一个主页面肯定是个艺术家信息列表,而且是动态列表。但是客户需要的是快速实现,他不想听你逼逼动态列表好不好做,也不想看你在那里煞笔的炫耀技术,你特么乖乖实现就行了。</p> <p>你可以自己从头搭建工程,当然考虑到看教程的大部分都是懒逼,这里给你们准备了一份初始工程,如果你不想搞事,劝你还是老实点用我这份比较好,Understand。。。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/1a9bec8d47e7fe349abef7e56c0a4e31.jpg"></p> <p>接下来我们就可以开始涨姿势了,Let’s go…</p> <h2>姿势Two:了解需求</h2> <p>由于我已经帮你模拟并拆解了需求,了解并分析你就免了,跟着看就成。。。</p> <p>打开 Artistry 工程,找到 Views 分组,点开 Main.storyboard :</p> <p><img src="https://simg.open-open.com/show/8bde8e9d89cfba2d668c0a2c931d9122.png" alt="Table View Cell 自适应速成大法" width="1192" height="377"></p> <p>从左到右分别是:</p> <ul> <li>作为根控制器的导航控制器。</li> <li>ArtistListViewController 负责显示艺术家列表。</li> <li>ArtistDetailViewController 负责显示艺术家作品以及详情。</li> </ul> <p>让我们跑一盘,可以看到 ArtistListViewController 显示了一个艺术家的列表,我们选择第一个艺术家(Pablo Picasso),页面跳转到 ArtistDetailViewController 显示艺术家作品介绍:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/1b73c3fe2b349b012c9b99e88bd6581e.png"></p> <p>作为一个艺术家,不应该单单只有文字的介绍,还需要图片,但是在这里我们并没看到图片信息,所以我们需要添加图片显示,那么由于图片的宽高大小并不统一,因此你不可能只用一个固定高度就能解决,而是需要基于Cell内包含内容才决定的动态高度。</p> <p>那么我们接下来就在 ArtistListViewController 利用动态高度实现Cell的自适应。</p> <h2>姿势Three:Cell自适应</h2> <p>想要获得Cell的正确高度,必须自定义一个Cell并且使用AutoLayout建立正确约束。</p> <p>这里我们可以使用 Command + N 快捷键来创建文件,Cell是属于视图结构,因此最好是放到 Views 分组下,你要不喜欢可以随便放,做项目要保持烂习惯也是你自己遭殃。</p> <p>OK,这里我们选择 Cocoa Touch Class 创建一个名为 ArtistTableViewCell 并且继承自 UITableViewCell 的源文件。语言项肯定是整 Swift ,也不需要创建 Xib 可是文件哈,你踏马要煞笔到怼Objc我也无话可说,那到这里我劝你赶紧Q掉。</p> <p>打开我们刚才创建的 ArtistTableViewCell.swift 并删掉系统自动生成的方法,接着我们添加如下属性:</p> <pre> <code class="language-objectivec">@IBOutlet weak var bioLabel: UILabel! </code></pre> <p>接着,点开 Main.storyboard ,在 ArtistListViewController 里选中 TableView 的 Cell ,在 Identity Inspector 就是识别检查器, Command + Option + 3 也可以,都是一个屌意思,把 Class 栏修改为 ArtistTableViewCell 才能跟代码绑定。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/d66d6bcd6d37373f9038f51cf30c7cf9.png"></p> <p>拖一个 UILabel 到刚才的 Cell 里,并把内容改为 Bio ,然后在 Attributes Inspector 属性检查器里把 Lines 设置为0,Label要是现实多行文字这个是必须的前提,OK,搞定之后看起就想这样:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/d8f5b611c0cc3e52d05c2064c4dc5452.png"></p> <p>刚才我们设置的那个 Lines 也就是Label对应的断行属性 numberOfLines ,这个我就奶妈当到底吧,这个属性是 Int 类型,设置几就是只显示几行,设置 0 就是完整显示,千万别忘了设置,不然你就是当不插电开机的煞笔好了。</p> <p>接下来在 Document Outline 找到刚才绑定的Cell上右键,在弹出的outlet弹出列表上把 ArtistTableViewCell 的属性 bioLabel 拖到刚才弄的内容为 Bio 的Label上链接起来,演示如下:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/51b6f96c89d330ec9b5f31edc86c3dd5.png"></p> <p>是不是憋的一逼,一开始到现在咋都不说这么做是为啥,现在就告诉你为什么,让 UITableViewCell 动态高度的秘诀是利用 AutoLayout 里有内建高度的控件比如 UILabel 这种来把Cell撑开,这种做法的前提就是必须把约束给设置完整,不然系统就没法自动计算高度。</p> <p>刚才原理都明白了我们可以给Label拉约束了,在Storyboard可视化界面的直接快捷添加,只需要让 Label 的四边顶住Cell的四边即可,也就是给Label分别四个约束添加:</p> <ul> <li>leading</li> <li>top</li> <li>trailing</li> <li>bottom <p style="text-align:center"><img src="https://simg.open-open.com/show/efd74d2ab6e380f55e3b270c603f56dc.png" alt="Table View Cell 自适应速成大法" width="345" height="424"></p> </li> </ul> <p>关于 Constraints to margins 这个选项这里还是说一下,这个选项是留边的做法,最开始是 Size Class 这个特性考虑不全,认为所有人都会为同一个应用在 Storyboard 里掺杂各种屏幕的页面设计,也就是 iWatch 的诞生才引入的 Size Class 特性。</p> <p>但是大部分日常开发都是基于iPhone,然后才是iPad,iWatch,所以这个作为默认勾选在iPhone上是很多新手踩的大坑,如果没注意又不知道意思,勾选之后在不同屏幕上看到的边缘就会有留边或者被裁掉的问题。</p> <p>所以在Xcode8.1之后如果是iPhone模板做页面设计,是已经取消默认勾选。</p> <p>所以根据你Xcode的版本,总之就是取消勾选个 Constraints to margins ,然后上下左右四个约束的约束值:</p> <ul> <li>上下约束值为0</li> <li>左右约束值为8</li> </ul> <p>那么我们来验证一下上面做的是否满足AutoLayout的标准:</p> <ul> <li>控件的起始点和宽高都能确定吗?有上下左右四边约束,这是绝逼能确定起始点和宽高的,通过。</li> <li>可变控件是否把Cell的内容视图 contentView 给顶住?Label上下两边的约束就足够顶住,通过。</li> </ul> <p>所以这个自动布局完全可以确定高度以便让Cell高度自适应。</p> <p>现在你的 ArtistTableViewCell 视图已经搞定,让我们跑一盘来看看:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/b5539c4717fb5f4d12768e484a9775b5.png"></p> <p>不对啊,咋还是之前的屌样,What the fuck!???莫紧张,我们只是弄了可视化绑定部分,你以为还真的全程可视化啊,当然还是写点小代码,别太天真了骚年!!!</p> <p> </p> <p>来自:http://www.rockerhx.com/2016/12/12/2016-12-12-Self-sizing-Table-View-Cells/</p> <p> </p>