如何在iOS 13上最初隐藏导航控制器中的搜索栏?

17

iOS 13的行为发生了变化,当导航控制器出现时,默认情况下搜索栏是可见的(当将UISearchController分配给navigationItem.searchController时)。一些系统应用程序出现时搜索栏被隐藏(需要向下滑动才能显示),但我没有看到任何特定的属性可以允许这样做。怎么实现呢?也许有一些属性或方法可以做到这一点?


导航控制器默认情况下没有搜索栏,因此请更新您的问题并提供有关如何放置搜索栏的详细信息。 - rmaddy
@rmaddy 我会的,只是想知道你是否真的不知道我在做什么,因为自从iOS 11以来,在导航控制器中显示搜索栏是标准程序。 - Ivan Ičin
有不同的解决方案,因此重要的是您清楚地知道自己正在做什么。您的编辑远远不够详细。 - rmaddy
@rmaddy,由于有些人(可能包括你)会给你的回答投反对票,请回答一下你所缺少的内容。你是否尝试使用上述描述来重现问题?我可以这样做,而且我不明白搜索栏控制器的实现会如何影响它,因为即使最简单的搜索栏控制器也能正常工作。 - Ivan Ičin
9
这个问题对我来说似乎很明确。带有搜索控制器(即带有搜索栏)的导航项在iOS 13中的行为与以前不同 - 它们在加载时可见。常规的想法(设置表格的内容偏移量,或以编程方式将表格滚动到第一行)都不起作用。 - Andrew Bennet
8个回答

9

通过实验,我发现如果在viewWillLayoutSubviewsviewDidLayoutSubviews中延迟将搜索控制器分配给导航项,搜索控制器就会按照预期始终隐藏。但是,在iOS 12或更早版本中这样做时,当向下滚动时搜索控制器不会被显示。

最后我进行了一个混乱的版本检查,以下是我的解决方案:

override func viewDidLoad() {
    super.viewDidLoad()

    searchController = /* make search controller... */

    if #available(iOS 13, *) {
        // Attaching the search controller at this time on iOS 13 results in the
        // search bar being initially visible, so assign it later
    }
    else {
        navigationItem.searchController = searchController
    }
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    navigationItem.searchController = searchController
}


6
这听起来很有前途,我已经点赞了,但至少对我来说没有任何效果,所以可能只在某些情况下有效。 - Ivan Ičin
原帖就是我遇到的确切问题,这个解决方案对我很有帮助。谢谢@bunnyhero。 - sirshannon
对我没有起作用——顺便问一下,这是您的应用程序的初始 VC 还是其他 VC? - royherma
1
我有一个Tab bar控制器(初始vc)->根vc是带有UITableView的UIViewController的Nav Controller,我无法在加载期间隐藏搜索栏..尝试了一切:( @bunnyhero - royherma
2
如果在 viewWillLayoutSubviewsviewDidLayoutSubviews 中无法正常工作,请尝试在 viewDidAppear 中执行。这对我很有效! - Avery Vine
显示剩余2条评论

6

若想要开始使用隐藏的 searchBar,只需在你的表格视图(或集合视图)填充数据后,设置导航项.searchController属性即可。


这些答案都对我没用。采用这种方法,要么它根本不在那里,直到我切换到另一个视图然后再切回来,要么它已经在那里了。看起来有点随机,有一次它突然出现了,一点也不顺畅。我感觉他们不想把它隐藏起来。在我正在学习的这个教程中,他说你“可能”需要下拉才能看到它,但当我运行他的示例时,它已经在那里了。https://www.raywenderlich.com/4363809-uisearchcontroller-tutorial-getting-started 可能取决于iOS版本。 - Kurt L.

3

受到bunnyhero的回答的启发,我将设置UISearchControllernavigationItem中的代码放在了viewDidAppear方法中。在iOS 14/15上,这似乎每次都有效。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    if navigationItem.searchController == nil {
        navigationItem.searchController = searchController
    }
}

编辑:我过于乐观了。在iOS 15.2上,这种方法对我不起作用。我所做的是在重新加载表格/集合视图后移动代码来修复它。


即使我在collectionView重新加载后按顺序设置了searchBar,也无法获得所需的行为。最终,我通过使用DispatchQueue.main.asyncAfter(deadline: .now() + 0.1)延迟搜索栏设置来使其正常工作。 - theogood

1

这是对我有效的方法。我有一个UISegmentedControl,当筛选器更改时重新加载tableView。

使用FRC:

guard let count = try? fetchedResultsController.managedObjectContext.count(for: request) else { return }

在tableView.reloadData()之后调用

navigationItem.searchController = count > 20 ? searchController : nil

0

在设置searchController之前,应该先获取tableView的frame。

override func scrollViewDidScroll(_ scrollView: UIScrollView) {
    super.scrollViewDidScroll(scrollView)

    if !scrollView.frame.isEmpty, navigationItem.searchController == nil {
        navigationItem.searchController = searchController
    }
}

0
我发现这个方法可行: < p > < code > self.searchController.searchBar.hidden = YES; 你需要在适当的时候取消隐藏。

1
我猜在某种程度上它会起作用。但我不认为它像邮件应用程序那样,在向下滚动时出现动画效果的状态栏。 - Ivan Ičin

0
我通过在navigationBar上设置isTransculent为false并在UITableView或UICollectionView上有初始数据来使其工作。如果最初没有cell并在一段时间后触发reloadData(也许是网络调用),则SearchBar最初可见。因此,最初先有一个虚拟单元格或类似的东西,稍后再加载数据,如果您的情况是这种情况。
navigationController?.navigationBar.isTranslucent = false

-2

Swift 5.2 & iOS 13.3.1:

试试这样做,它可以正常工作。

        navigationItem.hidesSearchBarWhenScrolling = false

1
你试过了吗?根据文档,它不是那样工作的:https://developer.apple.com/documentation/uikit/uinavigationitem/2897296-hidessearchbarwhenscrolling - Ivan Ičin

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