UITableVIew的高度和AutoLayout

作为一个android开发移民,在知晓UITableView可能会计算每一个cell的高度时,心里面还是惊了一下。Android的开发文档中,不会有关于计算高度这方面的内容,数据的多少和排版决定高度数值的大小不假,但去“感知”自己的高度难道不是ui组件分内的事儿吗?

可惜这种疑问并没有支撑多久,因为大脑的另一侧已经出现android自适应高度时各种坑和bug,比如在ScrollView当中创建ListView,会发现设置成为自适应高度、多行数据的ListView变成细细一杠,让每一个新手开发大脑回旋“What the fu*k”,用手指拨动它还会上下滑动,像极了LED。至少就动态计算列表高度这一点上,ios和android都没长出什么甜果子。

好了,我只需要知道,一个展示大量列表数据的滑动组件想知道自己的高度,就得计算各个子view的高度,即UITableView需要知道每一个UITableViewCell的高度,这样一来,就算是每个UITableViewCell的高度大小不一,也能完美显示。


UITableVIew的高度和AutoLayout_第1张图片
(不同高度的cell,图来自[www.raywenderlich.com](http://www.raywenderlich.com/87975/dynamic-table-view-cell-height-ios-8-swift))

那么如何计算每一个UITableViewCell的高度呢?很简单,分两步:

  1. 用systemLayoutSizeFittingSize:UILayoutFittingCompressedSize获取高度。
  2. 在heightForRowAtIndexPath当中返回这个高度。
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        if(cell != nil) { 
           let size: CGSize = (cell?.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize))!
           return (size.height + 1)
        }
           return 0
    }

需要解释的地方在于这个“return (size.height+1)”,为什么要加1?因为这里获取的size是cell当中contentView的size,cell作为老子肯定要比儿子高一头啦,不然怎么管得住儿子?

Cell = ContentView(size.height) + Separator(1px)

利用systemLayoutSizeFittingSize获取cell中contentView的size还有一个前提,就是contentView需要设定constraints,所以实际上这是一个与Auto Layout配套的高度获取方式。


UITableVIew的高度和AutoLayout_第2张图片
systemLayoutSizeFittingSize解释

为每个cell计算高度再相加会得到整个UITableView的高度,问题也在于每个cell的计算过程会耗费时间,有大量cell的时候会使得整个ui展示的效率不高,怎么办呢?

这里有一个聪明的概念上的划分,就是“能够被用户看见的cell”和“用户还没有看见的cell”。这里可能有上千行数据,作为系统而言,它计算了每个cell的高度,但是手机屏幕高度有限,只看得到几个cell,这种大量的计算不是很浪费么?就好比我是一家生意红火餐馆,能坐200桌客人,吃饭高峰期我们家客满了,还会在门外等50桌客人,我有必要为这等待的50桌客人备好菜么?我只需要知道等待的这50桌人大概会吃多少菜,保证厨房中的原料足够就可以了。UITableView也有这么一个功能,给还没有看见的cell一个估计的高度,这样既能知道自己的高度大概是多少,又不造成浪费,提高效率。

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 78
}

你可能感兴趣的:(UITableVIew的高度和AutoLayout)