在上文中。我们讲了单一样式的UITableViewCell
在Autolayout下的动态高度,本文将在上文的基础上,增加两个地方:
1. 多个样式的UITableViewCell
类型。
2. UITableViewCell
样式动态变化变化。
完成这样一个程序,TableView中的Cell模拟下载过程,等“下载”完成后,切换到另一个样式的Cell。两种样式的Cell都是使用Autolayout规划,可以正确运行在iOS 7和iOS 6中(Autolayout最低要求iOS 6),如下图:
(可以看到下载过程中只能显示7个Cell,但是下载完成后Cell高度发生了变化,可以显示8个项目)
整个执行方式实际上就是沿用上文的描述的方法,即在heightForRowAtIndexPath
中使用一个Cell做测量并返回高度,在cellForRowAtIndexPath
中继续使用Cell重用机制。只不过这里是两个样式的Cell,所以在UITableView
的heightForRowAtIndexPath
方法中,要准本好两个供测量的Cell。当然,Cell内容加载也是两个。具体改用哪种Cell,是根据数据源中的特定数据,在本例中,当然就是是否指示下载完成的属性。
至于数据变化后Cell的刷新,调用UITableView
的reloadRowsAtIndexPaths
方法就OK了。来简单说一下实现过程(具体请参考源代码)。
首先,选中Storyboard中TableView,把Prototype Cells从1改成2。这样就有两个Prototype Cell了:
然后设计好两个Cell的UI:
注意每个Cell都定义好Autolayout,并且上下都连接上Constraint,否则systemLayoutSizeFittingSize
方法不会返回正确的结果,如下图:
最后别忘了为每一个Cell设置自己的Reuse Identifier。
代码上,多数代码和上文的完全类似,这里就不再多贴了。
看几个比较重要的,比如heightForRowAtIndexPath
方法,只创建两个Cell来测量,Cell的内容加载和测量高度返回和上文讲的类似。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { [[GlobalCounter getInstance] add:@"get height"]; //Cell均只创建一次 static NormalCell *normalCell = nil; static CompletedCell *compCell = nil; MyTask *task = [_tasks objectAtIndex:indexPath.row]; if (task.isCompleted) { if (!compCell) //加载一种Cell compCell = [self getCompletedCell:task]; return [self getCellHeight:compCell]; } else { if (!normalCell) //加载另一种Cell normalCell = [self getNormalCell:task]; return [self getCellHeight:normalCell]; } }
还有cellForRowAtIndexPath
方法,直接调用加载Cell的方法就可以了:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { [[GlobalCounter getInstance] add:@"get cell"]; MyTask *task = [_tasks objectAtIndex:indexPath.row]; if (task.isCompleted) { return [self getCompletedCell:task]; } else { return [self getNormalCell:task]; } }
源代码下载
mgen_cellTemplates.zip
源代码环境:Xcode 6.0