UISearchController在UIBarPositionTopAttached时会导致UISearchBar超出屏幕;是否不可能在UITableView中使用标准的UISearchController?

7

我试图创建类似于iOS 8中的联系人应用程序的体验。其主要组件包括:

  1. 使搜索栏固定在导航栏下方
  2. 在展示时,将搜索栏附加到视图顶部(标准功能)。

然而,这比说起来容易得多。经过一段时间与tableHeaderView(不允许在表视图前进行交互,并且使用viewDidLayoutSubviews定位复杂)的斗争后,我决定在UIViewController中嵌入UITableView,以便可以将UISearchBar添加为子视图。这个方法效果还不错,可以在所有滚动位置与搜索栏进行交互,并且插图并不难计算。

但是,当激活时,搜索栏会被状态栏下面裁剪。这似乎是一个简单的问题,即使我在UITableViewController中的完全相同的实现中也没有遇到过这个问题。因此,我尝试确保在每个可能的视图控制器中设置了所有属性以进行对齐。

self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = YES;
self.automaticallyAdjustsScrollViewInsets = NO;

我已经尝试了所有可能的组合,包括在viewWillAppear和viewDidLoad中使用半透明导航栏、调整表格视图和搜索框的起始位置。但是没有成功。所以,我尝试调整框架或约束,也许使用topLayoutGuide或者只是0。然而,在任何一个UISearchControllerDelegate方法中调整框架实际上都没有调整其呈现的位置,而在活动动画开始时添加约束会立即崩溃(由于此时超级顶部在视图层次结构中不存在;在willPresent中删除约束完全没有效果)。
在挣扎了一段时间后,我尝试将positionForBar作为UISearchBar的委托实现:
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar {
    return UIBarPositionTopAttached;
}

这似乎调整了高度,但搜索栏飞到了视图的顶部。当激活时,搜索栏似乎直接出现在可见区域的上方。这甚至比它被裁剪在UIStatusBar后面或下面更糟糕。我还尝试在搜索控制器变为活动状态时只隐藏状态栏,但是条件实现prefersStatusBarHidden根本不起作用(在没有UISearchController活动时返回YES非常好,但当活动时它会再次显示状态栏,或者显示在其下面)。我认为这是因为UISearchController拒绝遵守任何标准或规则,现在这一点已经非常明显了。

debug hierarchyinactive stateactive state

我已经尝试了几天来解决这个问题,除了重新实现UISearchController类/动画之外,我想不到其他的解决办法。请帮忙!

4个回答

0

对我有效的方法是子类化UISearchController,并在子类中重写prefersStatusBarHidden

还要确保“基于视图控制器的状态栏外观”设置为YES

并在包含表格视图/搜索栏的视图控制器中:

self.definesPresentationContext = YES;

0

我的理解是,如果您需要在导航栏下方添加搜索栏,就像您在#1中提到的那样,只需设置一个布尔值(#1的解决方案)searchController.hidesNavigationBarDuringPresentation = true

不幸的是,我无法修复当导航栏隐藏时搜索栏脱离屏幕的问题。


0

我有同样的问题。我将UISearchController添加到UIViewController中,而不是使用tableView.header。而且UISearchBar.superview.frame.origin.y为-44。所以你看不到搜索栏。

方法1:你可以在UISearchControllerDelegatedidPresentSearchController方法中更改UISearchBarWrapperView的框架。但你会看到这个过程的动画。

方法2:像JBlake说的那样。在UISearchControllerinit后设置self.definesPresentationContext = YES;。它有效!


0

根据您所描述的行为,这对我来说非常有效。

var resultSearchController = UISearchController()

在你的viewDidLoad函数中添加以下内容:
//Search Bar
        self.resultSearchController = ({
            let controller = UISearchController(searchResultsController: nil)
            controller.searchResultsUpdater = self
            controller.searchBar.sizeToFit()
            controller.dimsBackgroundDuringPresentation = false

            self.tableView.tableHeaderView = controller.searchBar
            self.definesPresentationContext = true
            return controller
        })()

谢谢您的回复!不幸的是,尽管这种实现方式很好,但它并不能满足我在问题顶部提出的要求(#1和#2)。我需要搜索栏即使在滚动时也保持固定。 - insanj
@insanj,你尝试过将搜索栏的框架设置为视图滚动中的y平移吗? - cyril
不,这在这种情况下没有意义。我已经将搜索栏直接添加为子视图,在表视图之上。如果它是一个tableHeaderView,那可能有意义,但那个解决方案也不完美(触摸会穿过)。如果你也许是指搜索结果表视图的y-平移,那似乎也太晚了:最终,我需要在任何滚动之前进行框架调整(在任何搜索之前它都会变暗,直到搜索完成(标准的UISearchController),并且没有didScroll发生)。 - insanj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接