Как изначально отобразить панель поиска на панели навигации, но при этом скрыть ее при прокрутке пользователем вверх?

#swift #uinavigationbar #uisearchbar

#swift #uinavigationbar #панель пользовательского поиска

Вопрос:

Я создаю базовый ViewController, содержащий CollectionViewController с несколькими разделами. Я хотел бы, чтобы панель пользовательского поиска содержалась на панели навигации, но, похоже, 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
}
  

Я знаю, что этот код не приведет к ожидаемому поведению, но есть ли простая модификация, которую я мог бы внести, чтобы она вела себя должным образом?

Комментарии:

1. » приложение «Сообщения», где оно появляется без необходимости прокрутки пользователем, «, ну, когда вы просто запускаете приложение «Сообщения», оно не отображает поле поиска по умолчанию и отображается только при прокрутке вверх, когда вы находитесь наверху

2. Ну, почему бы вам не установить первую ячейку вашего пользовательского CollectionView в качестве строки поиска, таким образом, всякий раз, когда загружается CollectionView, строка поиска всегда будет присутствовать вверху, и при прокрутке она будет скрыта, а затем, когда вы снова прокрутите до верха, она будет видна . Но это, похоже, не является частью панели навигации

Ответ №1:

Я нашел способ изначально отобразить панель пользовательского поиска. На данный момент я не совсем уверен, предназначено ли это Apple или это просто еще один взлом, чтобы заставить простое поведение работать.

В viewDidLoad после настройки вашего UISearchController вызова:

 present(searchController, animated: true)
  

Затем это оживит и расширит панель навигации и покажет панель поиска. Не забудьте снова отключить ее, когда закончите редактировать текст внутри панели. Это необходимо сделать, даже если вы изначально скрываете панель поиска, потому что в противном случае она будет сохранена, и в итоге произойдет утечка.

Редактировать: Чтобы ответить на остальную часть вашего вопроса, я предоставил некоторый демонстрационный код, чтобы донести идею:

Вы можете наблюдать за 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 использует простое расширение, найденное и объясненное здесь, но использование стандартной версии библиотеки также работает.

Ответ №2:

Установите hidesSearchBarWhenScrolling = true в viewDidLoad()

Установите для параметра contentOffset для просмотра прокрутки значение, обратное высоте панели поиска в viewWillAppear().

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

Ответ №3:

Сделайте подобное в viewDidLoad

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

Ответ №4:

Лучший способ — использовать возможности UISearchController без использования вашего ScrollView.

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

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

    self.navigationItem.hidesSearchBarWhenScrolling = true
}