iOS让自定义行高变得如此简单!

在iOS开发中,iOS8.0以前tableview自适应行高是一个非常难处理的问题。本文讲述一下几种自适应行高的方法。

  • iOS8.0+自适应行高的方式。
    直接使用以下两行代码即可:
self.tableview.estimatedRowHeight = 44
//以下可以不写,默认值
self.tableView.rowHeight = UITableViewAutomaticDimension
  • iOS7.0+适应行高的方式。
    1.使用autolayout的方式加载视图,配合tableview中的heightForRowAt来实现。
    2.配合tableview中的estimatedHeightForRowAt返回UITableViewAutomaticDimension来实现自适应行高。

下面我们来讲解工程。
本工程运用swift编写,入口是RootViewController。
我们定义全局常量文件:GlobalConst.swift,如下,存储当前需要的数据。

var contentAry:[String] = ["人生有三重境界,这三重境界可以用一段充满禅机的语言来说明,这段语言便是:看山是山,看水是水;看山不是山,看水不是水;看山还是山,看水还是水","这就是说一个人的人生之初纯洁无暇,初识世界,一切都是新鲜的,眼睛看见什么就是什么,人家告诉他这是山,他就认识了山,告诉他这是水,他就认识了水","随着年龄渐长,经历的世事渐多,就发现这个世界的问题了。这个世界的问题越来越多,越来越复杂,经常是黑白颠倒,是非混淆,无理走天下,有理寸步难行,好人无好报,恶人千年。进入这个阶段,热是激情的,不平的,忧虑的,疑问的,警惕的,复杂的。人不愿意再轻易地相信什么。人在这个时候看山也感慨,看水也叹息,借古讽今,指桑骂槐。山自然不再是单纯的山,水自然不再是单纯的水。一切的一切都是人的主观意志的载体,所谓好风凭借力,送我上青云。倘若留在人生的这一阶段,那就苦了这条命了。人就会在山望了那山高,不停地攀登,争强好胜,与人比较,怎么做人,如何处世,绞尽脑汁,机关算尽,永无满足的一天,因为这个世界原本就是一个圆的,人外还有人,天外还有天,循环往复,绿水常流。而人的生命是短暂的有限的,哪里能够去与永恒和无限计较呢?","许多人到了人生的第二重境界就到了人生的终点。追求一生,劳碌一生,心高气傲一生,最后发现自己并没有达到自己的理想,于是抱恨终生。但是有一些人通过自己的修炼,终于把自己提升到了第三重人生境界。茅塞顿开,回归自然。人在这时候便会专心致志做自己应该做的事情,不与旁人有任何计较。任你红尘滚滚,自有清风朗月。面对芜杂世俗之事,一笑了之,了了有何不了。这个时候的人看山又是山,看水又是水了。正是:人本是人,不必刻意去做人;世本是世,无须精心去处世;便也是真正的做人与处世了。"];

在RootVC中,我们使用Storyboard的方式,加载tableview,创建cell,通以下方法通向其他界面。

  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        //项目的名称
        let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
        //当前的类名
        let curClassname = self.diffClass[Array(self.diffClass.keys)[indexPath.row]]!
        switch indexPath.row {
        case 0:
            let iOS8VC = iOS8ViewController.storyboardInstance()
            self.navigationController?.pushViewController(iOS8VC!, animated: true)
        case 1:
            let autoVC = AutoLayoutViewController.init()
            self.navigationController?.pushViewController(autoVC, animated: true)
        default:
            return
        }
    }

iOS8VC是也是一个Storyboard的文件,作者在此前看过此篇文章,为了加以实践才运用了这个方式去加载。此文件里面创建了普通的tableview,并且运用

self.tableview.estimatedRowHeight = 44

直接让文件自适应成功。


接下来,为了适配iOS7+,作者新建了AutoLayoutViewController。

  • 首先创建了AutoCell的xib,如下所示:
    autocell.png

    分别对上下左右进行了适配,并且设置宽度。在这里,我们需要注意的是要设置视图距离底部的距离,不然cell的高度永远为0。
    接下来,我们重写了heightForRowAt的方法,如下
 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//        let cell = tableview.cellForRow(at: indexPath) as! AutoCell?
        let cell = tableview.dequeueReusableCell(withIdentifier: "autocell") as! AutoCell?
        cell?.cellLabel.text = contentAry[indexPath.row]
        cell?.setNeedsUpdateConstraints()
        cell?.updateConstraintsIfNeeded()
//        CGFloat height = cell?.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
        let height = (cell?.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height)! as CGFloat
        return height + 1;
     }

其实此方法调用的时候,细心的程序员会发现,在tableview刚刚加载的时候,视图会调用此方法进行大量的运算,所以,如果数据过多,则必然会影响tableview的性能的问题。就像以前运用老一点的方法,用一个数组保存当前tableview需要刷新的内容,然后运用boundingRectWithSize 运算的时候,会有问题。并且,此方法是在func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell之前运行一次的,所以我们得小心运用,防止程序崩溃。
当然,还好苹果在iOS7+提供了

// 对可变cell 高度的估算
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {}

接口,让我们能够在程序运行之前估算当前cell的值而不进行运算。接下来我们只用调用以下方法,即可完成我们想要的结果。

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }

此原理:首先利用autolayout来让cell里面的控件进行自己适配,然后在heightForRowAt上进行运算撑开cell。


当然,如果我们需要适配iOS6+的方法,我们则可以运用第三方框架来完成我们的需求,在github上有一个非常有效的框架FDTemplateLayoutCell


关于优化,有两种方式,第一种就是尽量不要在heightForRowAt里面使用大量的运算,最好是先用estimatedHeightForRowAt或者tableview.estimatedRowHeight来让tableview出现的时候先估算出高度,然后再进行渲染。第二种就是将当前计算的值给保存起来,防止下一次渲染的时候再进行运算。

Demo 地址
如有错误,欢迎指点,谢谢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,982评论 4 60
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一种新的协议。它实...
    香橙柚子阅读 23,615评论 8 183
  • 2017101410苏展 W4 英语自学复盘 Unit2 TextA A Language Teacher's P...
    数410苏展阅读 205评论 0 0
  • 太阳之为病,脉浮,头项强痛而恶寒。 太阳病,发热,汗出,恶风,脈缓者,名为中风。 太阳病,或已发热,或未发热,必恶...
    两颗蛀牙阅读 559评论 0 0
  • 2017年8月7日,今天立秋了,太原天气多云。
    皇冠梨阅读 81评论 0 0