类似于原生联系人应用程序的粘性搜索栏和部分标题行为

Posted

技术标签:

【中文标题】类似于原生联系人应用程序的粘性搜索栏和部分标题行为【英文标题】:Sticky search bar and section header behavior similar to native Contacts app 【发布时间】:2013-02-07 19:36:01 【问题描述】:

我想复制 iPhone 通讯录应用中搜索栏的粘性行为。

当用户向下滚动视图时,搜索栏也会随着视图一起向下移动

如果用户向上滚动,表格也会随之滚动,有以下两种行为:

(1) 搜索栏保持固定在顶部,并且 (2) 后续章节标题适当地停在搜索栏下方

当下一个section header到来时,前一个header消失在搜索栏下方:

注意:部分索引控件(右侧的 a-z)也会出现在搜索栏的顶部。因此,摆弄contentInset 会将部分索引控件随之向下推。

我创建了一个自定义UIViewController,添加了一个UITableView,将其contentInset 设置为搜索栏的高度。我创建了一个UIView,将搜索栏添加为其子视图,然后将UIView 添加到UITableView。但是,如上所述,当用户滚动时,节标题仍停留在 y 位置零处,而不是标题高度。此外,节头索引控制位置也会受到不利影响。

我很感激这个问题的解决方案。

【问题讨论】:

定位搜索栏是很容易的部分,您可以使用内容插入使节标题停在正确的位置。困难的部分是(1)您必须不断将搜索栏向前移动,以便新的部分标题不会在它前面交叉,以及(2)我不知道如何使索引更高以抵消内容插图。我怀疑 Apple 可以访问我们没有的 API。 可能。我一开始应该提到我已经摆弄了UITableView 的内部工作,并访问了UITableViewIndex 并修改了它的位置+行为。然而,这是不明智的,因为苹果很可能会拒绝这种公然滥用其 API 的行为 我认为我们必须得出结论,没有办法做你想做的事。应该有!这是一个很好的界面,因为它使搜索字段很容易找到。我建议提交一份错误报告,要求进行改进。同时,我推荐 iPad 上 Mail 应用程序使用的界面,其中搜索栏不是表格视图的一部分。我确实知道如何实现这一目标! :) 虽然仅使用公共 API 无法使部分索引控件与搜索栏重叠,但复制联系人应用程序的行为非常简单,我同意这对于大型列表非常方便。 :) 【参考方案1】:

要让所有事情都正确,已经做了相当多的工作,但我只需要证明可以重现这种行为,至少几乎。 查看我创建的这个 GitHub 项目:https://github.com/f***kr/TableViewSearchBar

其实也没那么复杂: 1)直接在table view中添加搜索栏,并设置tableView的contentInset 2) 在-scrollViewDidScroll: 调整搜索栏的边框

不过,您必须注意一些注意事项: 1) 将表格视图滚动到顶部时,部分标题会很快出现在搜索栏上方。为了解决它,在滚动到顶部时设置搜索栏的zPosition 2) 你的内容控制器需要是UIViewController 的子类而不是UITableViewController,因为UISearchDisplayController 将调光视图添加到控制器的视图中。因为表视图控制器的view是表视图,所以当表视图滚动时,调光视图会在错误的位置。

仅使用公共 API 无法实现的一件事是使表格右侧的部分索引控件与搜索栏重叠。这只是一件小事,即使没有它,其行为也与“通讯录”应用中的行为非常相似。

为了实现完全相同的行为,您必须使用私有 API。 UITableView 上有一个方法叫做 _setPinsTableHeaderView: 需要使用。示例项目包含以下两种实现:1) 仅公共 API 和 2) 私有 API,以使部分索引控件与搜索栏重叠。提醒:当您使用私有 API 时,您不应该使用私有 API。计划将应用提交到 App Store!

【讨论】:

+1 用于私有方法。让我们希望它会公开,这是有用的东西。如果有人真的真的想要索引重叠,那就自己做。这不是那么困难。【参考方案2】:

我实现此行为的方法是将我的浮动单元格从 UITableView 中分离出来,并使其成为 UITableView 的子视图,并在 scrollViewDidScroll 中为浮动单元格设置动画。 就这样 UITableView 向下滚动足够远以显示浮动单元格我还在 tableview 中粘贴了一个不可见的单元格,当调用 scrollViewDidScroll 时该单元格被浮动单元格覆盖。

- (void)viewDidLoad 
   // add floating cell to tableview
   FloatingCell *cell = [[FloatingCell alloc] init];
   [self.tableView addSubview:cell];
   self.floatingCell = cell; 

// overwrite scrollViewDidScroll
- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
    CGRect floatingCellFrame = floatingCell.frame;
    CGFloat floatingCellHeight = floatingCellFrame.size.height;

    // when contentOffset is is more then cellHeight scroll floating cell
    if (scrollView.contentOffset.y > floatingCellHeight) 
       floatingCellFrame.origin.y = -scrollView.contentOffset.y + floatingCellHeight; 

    // when contentOffset is less then cellHeight stick it to the top of UITableView
    else if (scrollView.contentOffset.y < floatingCellHeight)
       floatingCellFrame.origin.y = 0;

   floatingCell.frame = floatingCellFrame;

您可能需要在滚动时添加几个极端情况条件,以便浮动单元格不会出现跳跃,但这应该可以让您开始。祝你好运!

【讨论】:

这不可能。部分标题仍然位于表格顶部;他们不会按照 OP 的要求在搜索栏下方停止。如果您使用内容插图来尝试解决该问题,则部分索引太短;它不会与联系人应用程序中的搜索栏重叠。因此,此代码无法准确解决 OP 提出的问题。 你是对的,@matt。痛点是处理节标题和节索引控制。

以上是关于类似于原生联系人应用程序的粘性搜索栏和部分标题行为的主要内容,如果未能解决你的问题,请参考以下文章

实现类似于原生联系人搜索的搜索?

如何模仿棒棒糖联系人应用程序上的 listView 粘性项目?

tvOS UISearchController - 滚动时如何避免自动搜索栏和键盘隐藏行为?

导航栏和粘性 Bootstrap 页脚之间的 100% 高度

Android Studio是否具有类似于Xcode的快速跳转栏和MARK:-

用户在表格视图控制器中将行/部分添加到静态单元格