Пользовательская анимация для UISearchController?

Я представляю UISearchController из моего контроллера, встроенного в контроллер навигации. Появляется анимация по умолчанию, где окно поиска падает сверху вниз на панели навигации:

введите описание изображения здесь

Это не очень хороший UX в моем случае, потому что я представляю поиск, когда пользователь вступает в UITextField в середине экрана. То, что я хотел бы сделать, это иметь float UITextField сверху и преобразовать в поле поиска, но я не могу понять, как это сделать.

Это то, что у меня есть:

class PlacesSearchController: UISearchController, UISearchBarDelegate {

    convenience init(delegate: PlacesAutocompleteViewControllerDelegate) {

        let tableViewController = PlacesAutocompleteContainer(
            delegate: delegate
        )

        self.init(searchResultsController: tableViewController)

        self.searchResultsUpdater = tableViewController
        self.hidesNavigationBarDuringPresentation = false
        self.definesPresentationContext = true
        self.searchBar.placeholder = searchBarPlaceholder
    }
}

private extension ShowAddressViewController {

    @objc func streetAddressTextFieldEditingDidBegin() {
        present(placesSearchController, animated: true, completion: nil)
    }
}

Фактически вы можете загрузить и запустить пример приложения, которое делает это: https://expirebox.com/download/a105093cea111da24b310a35179e04dc.html

Вместо поиска, снижающегося сверху, я надеюсь, что текстовое поле выйдет на навигационную панель. То, что Im after - тот же эффект, что и в приложении iOS 11 File:

введите описание изображения здесь

Он имеет текстовое поле в середине экрана, а затем анимируется до панели навигации, когда вы нажимаете на него. В моем случае tho текстовое поле является более низким на экране, а не изначально частью навигационной панели.

Ответ 1

UISearchController

UISearchController - это компонент, который очень сложно настроить. Из моего опыта я могу сказать, что лучше использовать его, как без какой-либо радикальной или значительной настройки. В противном случае настройка может привести к беспорядочному коду, глобальным переменным состояния, трюкам выполнения с иерархией UIView и т.д. Если по-прежнему требуется определенное поведение, лучше реализовать контроллер поиска с нуля или использовать сторонний вариант.

Реализация по умолчанию

Похоже, UISearchController был разработан для использования в паре с UITableView и UISearchBar, установленными в виде заголовка таблицы. Даже примеры и документация официального кода Apple предоставляют такой пример использования (см. UISearchController). Попытка установить UISearchBar где-то еще часто приводит к многочисленным уродливым побочным эффектам с рамкой ракурса, позицией, подергиванием анимаций, изменениями ориентации и т.д.

Начиная с iOS 11, UINavigationItem получил свойство searchController. Это позволяет интегрировать контроллер поиска в ваш навигационный интерфейс, поэтому поиск будет выглядеть точно так же, как iOS Files или приложение App Store iOS. Поведение UISearchController по-прежнему связано с другим компонентом, но я считаю, что это лучше, чем соединение с UITableView все время.

Возможные решения

С моей точки зрения существует несколько возможных решений для вашей проблемы. Я предоставлю их в порядке увеличения усилий, необходимых для реализации:

  • Если вы все еще хотите использовать UISearchController, подумайте над его использованием, как без особых настроек. Apple предоставляет пример кода, который демонстрирует, как использовать UISearchController (см. Поиск таблиц с помощью UISearchController).
  • Существует несколько сторонних библиотек, которые могут быть более гибкими с большим количеством дополнительных функций. Например: YNSearch, PYSearch. Пожалуйста, посмотрите.
  • Наряду с представлением UISearchController вы можете попытаться переместить UITextField с изменением альфа от 1 до 0. Это создаст ощущение, что UITextField плавно трансформируется в UISearchBar. Этот подход описан в статье, которую предоставил Крис Слоуик (см. Комментарий к вашему оригинальному сообщению). Единственное, что я хотел бы улучшить, это анимация с использованием координаторов перехода (см. Пример здесь), это сделает анимацию более плавной с синхронизированным временем. Окончательная реализация также будет намного чище.
  • В качестве опции вы можете попробовать создать собственный контроллер поиска, используя только UISearchBar или даже простой UITextField.
  • Вы можете подклассифицировать UISearchController и добавить объект UITextField. UISearchController соответствует протоколам UIViewControllerAnimatedTransitioning и UIViewControllerTransitioningDelegate, где UITextFiled можно удалить или добавить вместе с анимацией перехода.

Надеюсь, это поможет.

Обновление:

Я реализовал подход, который я описал в пункте 3. Вот как это работает:

UISearchController с UITextField

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

Ответ 2

  • Создайте один UIView в XIB. назовите его searchView.
  • Добавьте UIButton внутри над UIView в том же xib и назовите его btnSearch. Как ниже  в вашем сценарии вы добавили текстовое поле, которое не является ментальным

  • Контроллер поиска в ViewDidLoad, как показано ниже:

    func setupSearchController()  {
      self.searchController = UISearchController(searchResultsController: nil)
      self.searchController.delegate = self
      self.searchController.searchBar.delegate = self
      definesPresentationContext = true
      self.searchController.dimsBackgroundDuringPresentation = false
      self.searchController.searchBar.sizeToFit()
      searchView.addSubview(self.searchController.searchBar)
      self.searchController.searchBar.isHidden = true
      self.searchController.searchBar.tintColor = UIColor.white
      self.searchController.searchBar.showsCancelButton = false
      UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = session?.makeColor(fromHexString: TYPE_COLOR, alpha: 1.0)
      self.searchController.searchBar.isTranslucent = false
      self.searchController.searchBar.barTintColor = UIColor(red: 239.0 / 255.0, green: 135.0 / 255.0, blue: 1.0 / 255.0, alpha: 1.0)
    }
    

    Этот метод будет автоматически настраивать searchcontroller внутри searchview.

  • Теперь вам нужно просто программно отобразить searchcontroller. добавьте метод щелчка кнопки на шаге 2. Вызовите это ниже имя метода showearchAnimation:

    func ShowSeachAnimation() {
      searchFrame = searchView.frame (add one global variable "searchFrame" in controller which saves searchView.frame so it will be used when cancel button clicked on search)
      self.btnSearch.isHidden = true        
      var yAxis : CGFloat = 20
      if #available(iOS 11 , *) {
         yAxis = 8
      } else  {
         yAxis = 20
      }
      searchView.translatesAutoresizingMaskIntoConstraints = true
      searchView.frame = CGRect(x: 0, y: yAxis, width: view.frame.size.width, height: view.frame.size.height - yAxis)
    
      self.searchController.searchBar.isHidden = false
      self.searchController.searchBar.becomeFirstResponder()
      self.searchController.searchBar.showsCancelButton = true
      self.searchBar(self.searchController.searchBar, textDidChange: "")
      searchView.layoutIfNeeded()
    }
    
  • Чтобы скрыть панель поиска, добавьте метод поиска поиска с именем "searchbarcancelbuttonclicked" в делегате searchcontroller:

    func searchViewHideAnimation()  {
      self.removeNavigationBar()
      self.navigationController?.isNavigationBarHidden = false
      self.searchController.searchBar.text = " "
      self.searchController.searchBar.isHidden = true
      UIView.animate(withDuration: 0.3, animations: {() -> Void in
          self.searchView.frame = self.searchFrame!
          self.btnSearch.isHidden = false
      }, completion: {(_ finished: Bool) -> Void in
          self.searchView.layoutIfNeeded()
      })
    }
    

Ответ 3

вы можете попробовать использовать https://github.com/Blackjacx/SHSearchBar, который по существу будет вашим текстовым полем. Вы можете добавить ограничения влево, вправо и вверх и отрегулировать верхнее ограничение, когда начнется редактирование текстового поля. В то же время вы скрываете навигационную панель, анимированную и серой, на фоне, используя представление наложения. Таким образом, у вас есть максимальный контроль над анимацией, и это приложение не так сложно, как может показаться.