swift 如何在NavigationBar中显示SearchBar,但在用户向上滚动时仍将其隐藏?

7d7tgy0s  于 2023-01-08  发布在  Swift
关注(0)|答案(4)|浏览(132)

我正在构建一个基本的ViewController,其中包含一个具有多个部分的CollectionViewController。我希望在NavigationBar中包含一个UISearchBar,但似乎Swift只允许两个行为选项:最初隐藏搜索栏,然后在用户向下滚动时显示它,或者总是显示搜索栏。
我希望搜索栏的功能能像消息应用一样,用户不需要滚动就能显示,然后在用户向下滚动页面时隐藏。我相信有一个简单的解决方案,但我对iOS开发相当陌生,还没有找到任何以前提出的问题。
搜索栏始终显示时的外观示例:

用户必须向下滚动才能显示搜索栏的外观示例:

控制器和搜索栏的初始化:

let searchController = UISearchController(searchResultsController: nil)

let searchBar: UISearchBar = {
    let search = UISearchBar()
    search.placeholder = "Search"
    search.translatesAutoresizingMaskIntoConstraints = false
    search.sizeToFit()
    search.barStyle = .default
    return search
}()

// Truncated...

// Called from viewDidLoad()
func configureSearchBar() {
    searchController.searchResultsUpdater = self
    searchController.obscuresBackgroundDuringPresentation = false
    searchController.searchBar.placeholder = "Search"
    searchController.searchBar.translatesAutoresizingMaskIntoConstraints = false
    searchController.isActive = true
    definesPresentationContext = true

    navigationItem.title = "Test Title"
    navigationItem.searchController = searchController
    navigationItem.hidesSearchBarWhenScrolling = false
}

我知道这段代码不会产生预期的行为,但是我可以做一个简单的修改来让它正常工作吗?

7kjnsjlb

7kjnsjlb1#

我找到了一种方法来显示UISearchbar,但现在我还不确定这是苹果的本意,还是只是为了让一个简单的行为正常工作而进行的另一次黑客攻击。
viewDidLoad中设置UISearchController呼叫后:

present(searchController, animated: true)

这将激活和扩展navigationBar并显示搜索栏。不要忘记在编辑完导航栏内的文本后再次关闭它。即使你最初隐藏了搜索栏,也需要这样做,因为如果你不这样做,它将被保留,最终导致泄漏。

**编辑:**为了回答您剩下的问题,我提供了一些演示代码来帮助您理解这个想法:

您可以观察contentOffset,并在它具有特定值时将其关闭:

observable = self.viewDictionary.tableView.observe(\.contentOffset) { [unowned self] value in
        guard let offset = value else { return }
        if offset.y > 30 {
            self.navigationItem.searchController?.dismiss(animated: true)
        }
    }

observer代码使用了一个简单的扩展find & explained here,但是使用标准库版本也可以。

cl25kdpy

cl25kdpy2#

在viewDidLoad()中设置hidesSearchBarWhenScrolling = true
将滚动视图contentOffset设置为viewWillAppear()中searchBar高度的倒数。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let offset = -(searchController.searchBar.frame.height)
    tableView.setContentOffset(CGPoint(x: 0, y: offset), animated: false)
}
dzjeubhm

dzjeubhm3#

在ViewDidLoad中执行类似操作

navigationItem.hidesSearchBarWhenScrolling = false
DispatchQueue.main.async {
    self.navigationItem.hidesSearchBarWhenScrolling = true
}
5kgi1eie

5kgi1eie4#

最好的方法是在不使用scrollView的情况下使用UISearchController的强大功能。

override func viewDidLoad() {
    super.viewDidLoad()
    
    navigationItem.hidesSearchBarWhenScrolling = false
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    self.navigationItem.hidesSearchBarWhenScrolling = true
}

相关问题