使用自定义 UITableView 子视图
Posted
技术标签:
【中文标题】使用自定义 UITableView 子视图【英文标题】:Working with custom UITableView subviews 【发布时间】:2013-11-28 14:03:14 【问题描述】:我有一个表视图控制器,我drag-and-drop an additional UIView
on a storyboard to make a header,它变成了UITableView
的子视图。
我不将其作为viewForHeaderInSection:
和朋友的“官方”部分标题(我将解释原因),它只是表格视图的子视图,它显示在顶部表,以及内部表视图包装器和视图层次结构中的刷新控制视图。
层次结构如下所示:
UITableView 0,0 320x455
UIRefreshControl 0,0 320x60
UITableViewWrapperView 0,0 320x455
cell 0,190 320x44
cell 0,146 320x44
cell 0,102 320x44
cell 0, 58 320x44
custom UIView 0,0 320x58
现在,标题视图运行良好......直到我想调整它的大小。这个想法是,标题视图有一个文本字段,当获得焦点时,会导致其他表单字段在其下方展开,从而将表格单元格向下推。
问题是我几乎无法控制单元格的布局。在调整自定义视图的大小(通过更改其框架)时,它会覆盖表格包装器视图。
那么,我为什么不把它变成一个节标题视图并通过heightForHeaderInSection:
调整它的大小呢?问题是,当一个文本字段被聚焦或输入时,我需要调用[self.tableView reloadData]
来刷新表中的数据(搜索时键入的东西),这也会重新加载标题并制作文本字段失去焦点。
总结一下,
-
如何实际制作可以动态调整大小和下推表格单元格的表格标题?
如何在重新加载表格时保持表格标题内的文本视图的焦点?
【问题讨论】:
试试这种方式怎么样 - 给你的表格两个部分,第一部分只有一个单元格,那个单元格将是你的“标题”。当您需要重新加载时,请使用 reloadSections: 仅重新加载第 1 节,这样您的“标题”就不会重新加载。 @rdelmar 我接受了这个想法。 另一件事 我没有提到的是,我有一个基本控制器类正在被其他类似视图使用,我必须将它重构为 2 节表视图,所以我避免了这种情况. @rdelmar 我刚刚意识到这也行不通,因为我需要重新加载顶部以使标题高度更改生效,这当然会破坏 UITextField 焦点... 你想让这个标题成为表格的子视图吗?您可以使用 UIView 控制器,并让此视图位于表格视图之外,还是这不适用于您的基本控制器设置? @rdelmar 我对结构并不太在意,只要它符合我的要求。但是,我找到了一个更简单的解决方案(见答案)。 【参考方案1】:tableHeaderView
的解决方案(与节标题视图无关):
-
将拖动的视图(或任何视图)分配给
self.tableView.tableHeaderView
。
如果你想改变它的高度,change its frame and assign it again。
视图将以新的高度重新绘制,但文本字段将保持焦点。
【讨论】:
我注意到,如果您将视图拖到 IB 中的表视图中,则不需要执行初始分配 - 如果您记录 self.tableView.tableHeaderView,您会发现拖in view 自动是表头视图。如果需要,您还可以使用 NSTimer 为标题扩展设置动画,方法是在每次增量更改高度后再次分配它。【参考方案2】:我还发现您需要将标题视图重新分配给表格视图的 tableHeaderView 属性以使其正确展开。接下来,我试图弄清楚如何为该效果设置动画。我可以使用 NSTimer 来做到这一点,在每次增加大小后重置表视图的 tableHeaderView 属性,但这看起来有点生涩。尝试在动画块中对其进行动画处理,导致了一些奇怪的效果——如果我更改了动画块中的高度(并重新分配了 tableHeaderView 属性),它对于小尺寸增加效果很好,但较大的尺寸会导致一些单元格动画开始时从屏幕底部消失(虽然在动画结束时,一切都很好)。最终,我发现改变表格视图本身的高度,并在完成块中将其更改回原来的大小,以及在完成块中(再次)改变标题的大小,一切都可以正常工作。
-(void)growHeaderBy:(NSInteger) delta
[UIView animateWithDuration:.6 animations:^
self.tableView.frame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.tableView.frame.size.height + delta);
self.header.frame = CGRectMake(self.headerFrame.origin.x, self.headerFrame.origin.y, self.headerFrame.size.width, self.headerFrame.size.height + delta);
self.tableView.tableHeaderView = self.header;
completion:^(BOOL finished)
self.tableView.frame = CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y, self.tableView.frame.size.width, self.tableView.frame.size.height - delta);
self.header.frame = CGRectMake(self.headerFrame.origin.x, self.headerFrame.origin.y, self.headerFrame.size.width, self.headerFrame.size.height + delta);
self.tableView.tableHeaderView = self.header;
];
headerFrame 是一个属性,在 viewDidLoad 中设置为标题视图的原始框架。
【讨论】:
以上是关于使用自定义 UITableView 子视图的主要内容,如果未能解决你的问题,请参考以下文章
如何使用子视图的延迟/动态加载实现自定义 UIView,类似于 UITableView
UITableView 可重用的自定义单元格在子视图中显示错误的内容
使用 Auto Layout 创建具有多个不同自定义单元格的 UITableView 具有几乎相同的子视图
实现 UITapGestureRecognizer 后 UITableView 不再响应
实现 UITableView (Slave) 的动态高度,它作为子视图添加到另一个具有动态高度的 UITableView (Master) 的自定义单元格中