从 UITableViewCell 嵌套 UITableView 衍生的一些想法和设计思路

单层 UITableView

  在 iOS 开发中总会用到 UITableView,最常见的 UITableView 的应用场景如下所示:

  首先,来分析一下这个 UI 页面中,每一个 UITableViewCell 的内容,由以下 5 个 UILabel 构成:

  1. 日期
  2. 酒店名称
  3. 入住时间 - 离店时间
  4. 酒店地址
  5. 入住人

假设内容高度固定(UILabel 行数为 1 行的情况)

  因为每个 UILabel 的高度固定,所以整个 UITabelViewCell 的高度也是一致的,在这种情况下,可以直接设置 UITableView 的单元格高度,使用:

self.tableView.rowHeight = 80; // 统一设置整个 UITableView 的单元格高度

然后自定义一个继承于 UITableViewCell 的 CustomCell 类,并且实现 UITableView dataSource 的相关方法:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.dataSource.count; 
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString * ID = @"CustomCellID";
    CustomCell * cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (cell == nil) {
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    return cell;
}

假设内容高度自适应(UILabel 行数为 n 行的情况)

  针对于:

  • 小屏幕手机无法展示全部的信息,只能以 … 作为结束
  • 有时候,需要展示的内容过长,也只能以 … 作为结束
      同样以上面的 UI 页面为例子,酒店名称有时候可能需要作为 2 行显示,甚至于 3 行,n 行都是有可能的;同样的,入住时间;酒店地址;入住人;都存在这种可能性,在这种情况下,有两种方法可以解决问题:

使用约束

  第一种方法,首先要了解 Autolayout 这个概念,它包含了两个重要的成员:

  • 约束:对控件位置和大小的限定条件
  • 参照:对空间设置的约束是相对于哪个视图而言的

同时,需要切记添加约束的 3 条规则:

  • 对于两个同层级 View 之间的约束关系,应该添加到它们的父 View 上
  • 对于两个不同层级 View 之间的约束关系,应该添加到它们最近的共同父 View 上
  • 对于有层次的两个 View 之间的约束关系,应该添加到层次较高的父 View 上

对于 xib 中设置约束,需要遵循的规则是:自上而下要有一条完整的约束线,从 cell 的 top 到 cell 的 bottom,同时 cell 中需要自适应高度的 UILabel 的行数都设置为 0

引入 frame 模型

  第二种方法,也是比较古老的方法,但很实用,就是在每一个 cell 的数据模型外面在套一个 frame 模型,这个 frame 模型包含一个数据模型,在 frame 模型的 set 数据模型的方法中,计算出 cell 每一个子控件的位置和大小,cell 中引入 frame 模型进行赋值,这种方法效率更高。

UITableViewCell 嵌套 UITableView

  除了上面这个比较简单的 UITableView,还有一些比较复杂的 UITableView,比如

假设高度固定

  阐述一下先添加后删除的方式并不好

假设高度不固定

  引入了 UITableViewCell 嵌套一个 UITableView 的想法,并且引入两个 frame 模型,并且需要提前计算得出第二个 UITableView 的高度,总结:还可以把计算高度的方法和设置数据源的方法抽出来 ..