UITableView - 如何在用户滚动时保持表格行固定
Posted
技术标签:
【中文标题】UITableView - 如何在用户滚动时保持表格行固定【英文标题】:UITableView - How to keep table rows fixed as user scrolls 【发布时间】:2012-06-05 08:50:28 【问题描述】:我希望能够在用户滚动时修复 UITableView 中某些行的位置。
具体来说,我有一个表格,其中某些行是后面行的“标题”,我希望标题在用户向上滚动时保持在屏幕顶部。然后,当用户滚动到下一个标题行将取代它的位置时,它会移开。
Any.DO 应用就是一个类似的例子。 “今天”、“明天”和“以后”表格行在屏幕上始终可见。
有人对如何实施有任何建议吗?
我目前正在考虑跟随 TableDidScroll 委托并将我自己的单元格放置在表格视图前面的适当位置。问题是,在其他时候,我真的希望这些单元格成为真正的表格单元格,以便它们可以被用户重新排序。
谢谢,
提姆
【问题讨论】:
为什么不使用 UITableView 标头?您可以将文本放在那里或制作自定义视图。有 UITableViewDelegate 的方法 【参考方案1】:我一直在玩这个,我想出了一个简单的解决方案。
首先,我们向控制器添加一个 UITableViewCell 属性。这应该被初始化,使其看起来与我们将用于创建虚假节标题的行单元格完全相同。
接下来,我们截取表格视图的滚动
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
// Add some logic here to determine the section header. For example, use
// indexPathsForVisibleRows to get the visible index paths, from which you
// should be able to get the table view row that corresponds to the current
// section header. How this works will be implementation dependent.
//
// If the current section header has changed since the pervious scroll request
// (because a new one should now be at the top of the screen) then you should
// update the contents.
IndexPath *indexPathOfCurrentHeaderCell = ... // Depends on implementation
UITableViewCell *headerCell = [self.tableView cellForRowAtIndexPath:indexPathOfCurrentHeaderCell];
// If it exists then it's on screen. Hide our false header
if (headerCell)
self.cellHeader.hidden = true;
// If it doesn't exist (not on screen) or if it's partially scrolled off the top,
// position our false header at the top of the screen
if (!headerCell || headerCell.frame.origin.y < self.tableView.contentOffset.y )
self.cellHeader.hidden = NO;
self.cellHeader.frame = CGRectMake(0, self.tableView.contentOffset.y, self.cellHeader.frame.size.width, self.cellHeader.frame.size.height);
// Make sure it's on top of all other cells
[self.tableView bringSubviewToFront:self.cellHeader];
最后,我们需要拦截对该单元格的操作并做正确的事情...
【讨论】:
非常感谢,塔姆斯。我正在寻找类似的东西,并且还需要在我的应用程序中实现您的逻辑。但是,我不明白你的意思是什么 headerCell ?当你的意思是 headerCell 在屏幕上? headerCell 是表格视图中您希望在滚动时保持在表格顶部的单元格。 问题:您说您使用它来重新排序标题。您是否折叠内容单元格以使标题重新排序更容易?我正在考虑,但不确定是否可行,因为reloadData
或其他类型的表格视图更新可能会中断/恢复浮动标题单元格。
要清楚 - 以防万一 - 我的意思是当用户点击处理程序开始拖动标题时,此时我想“关闭”这些部分,因此只有标题可见,并且将标题放在新位置更容易。我需要触发reloadData
或更新,以便在用户开始拖动时折叠这些部分,我认为这会取消拖动。
如果不可能的话,也可以有一个单独的按钮,用户可以手动折叠所有标题然后重新排序...但是如果可以在用户开始拖动时自动完成,那就太好了。 【参考方案2】:
这是纯 UITableView
实例中节标题的默认行为。
如果要创建自定义标题,请在表视图委托中实现 tableView:viewForHeaderInSection:
方法并返回标题的视图。
虽然您将不得不管理节和行,而不仅仅是行。
【讨论】:
问题是我希望能够记录节标题。据我所知,没有任何 UI 允许用户以与当前可以拖动部分行相同的方式执行此操作... 我明白了,您必须自己处理。看起来有点复杂,但我相信它可以完成。似乎没有任何实现。也许我可以帮助你,我们可以把它放在 Github 上。 有趣的是,现在在 ios5 中有一个 moveSection:toSection: 调用,但我认为没有办法从 UI 启动这个移动... 您可以将按钮或手势识别器添加到标题视图。这样您就可以在选择该部分时获得。【参考方案3】:Swift 5 解决方案
var header: UIView?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(indexPath: indexPath) as UITableViewCell
header = cell.contentView
return cell
func scrollViewDidScroll(_ scrollView: UIScrollView)
let headerCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0))
guard headerCell == nil || (headerCell!.frame.origin.y < self.tableView.contentOffset.y + headerCell!.frame.height/2) else
header?.isHidden = true
return
guard let hdr = header else return
hdr.isHidden = false
hdr.frame = CGRect(x: 0, y: tableView.contentOffset.y, width: hdr.frame.size.width, height: hdr.frame.size.height)
if !tableView.subviews.contains(hdr)
tableView.addSubview(hdr)
tableView.bringSubviewToFront(hdr)
【讨论】:
以上是关于UITableView - 如何在用户滚动时保持表格行固定的主要内容,如果未能解决你的问题,请参考以下文章
IOS - 滚动时将 UIView 保持在 UITableView 之上
UITableView 选定的单元格在滚动时不会保持选中状态
UITableView 在更新 NSFetchedResultsController 时保持滚动在正确的位置
为 UITableview 的高度设置动画时,滚动手势识别器保持相同大小