Подвиды в представленном ViewController после поворота получают неправильную позицию - PullRequest
4 голосов
/ 07 июня 2019

Я экспериментирую с UISearchController, но не могу понять это правильно. Я представляю чистый UISearchController от моего UIViewController, и это выглядит великолепно - но как только я поворачиваю устройство, оно сдвигается на несколько пунктов вверх или вниз.

Чтобы воссоздать это, просто выполните следующие несколько шагов:

  1. Создать новый проект Single View
  2. Удалить Main.storyboard из файлов проекта и удалить его имя из настроек проекта (Проект -> Общие -> Цель -> Основной интерфейс)

В AppDelegate.swift:

application didFinishLaunchingWithOptions...{
    window = UIWindow(frame: UIScreen.main.bounds)
    window?.rootViewController = ViewController()
    window?.makeKeyAndVisible()
    return true
}

ViewController.swift

class ViewController: UIViewController{
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .white
        let button = UIButton(frame: CGRect(x: 20, y: 200, width: 100, height: 40))
        button.setTitle("Search", for: .normal)
        button.backgroundColor = .black
        button.addTarget(self, action: #selector(click), for: .touchUpInside)
        self.view.addSubview(button)
    }
    @objc func click(){
        self.present(UISearchController(searchResultsController: nil), animated: true, completion: nil)
    }
}

И это все. Вот что я вижу: this

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

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

Это не вопрос размера высоты на панели. Весь бар толкается вверх / вниз.

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

debug

Если честно, я не совсем уверен, на что смотрю. Самый верхний вид - UISearchBarBackground, встроенный в _UISearchBarContainerView, который находится в пределах _UISearchControllerView.

Как вы можете видеть в инспекторе размеров с правой стороны, "контейнер" в среднем виде имеет y: 5, что не имеет смысла. При отладке правильного состояния у равно 0. Что действительно интересно, в этом поврежденном случае самое верхнее представление имеет y: -44 и то же самое, когда оно корректно - но вы можете ясно видеть, что есть некоторый остаток пространства выше Это. Кажется, есть три разных y-позиции. Я не понимаю.

Я прочитал несколько руководств о том, как реализовать UISearchController, но буквально каждый пример, который я нахожу, - это люди, которые модально представляют пользовательский ViewController, который содержит SearchController. Это приведет к тому, что весь пользовательский ViewController будет анимирован снизу.

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

Но почему это не работает?

Редактировать: Я только что узнал, что если я включу Hide status bar в настройках проекта, UISearchController выглядит даже более корректно в альбомной ориентации, чем "правильное состояние" сверху, и даже корректно анимирует к портрету. Это супер странно, потому что строка состояния вообще не меняется. Это никогда не было видно в ландшафте. Почему это происходит? Это кажется таким глючным. Посмотрите на эти три состояния: landscape

Первое состояние - при отображении контроллера поиска из портрета, а затем поворота в альбомную ориентацию (не имеет значения, включен Hide status bar или нет.

Второе состояние - при отображении контроллера поиска из ландшафта, если Hide status bar равно false

Третье состояние - при отображении контроллера поиска из пейзажа, если Hide status bar имеет значение true.

Ответы [ 4 ]

0 голосов
/ 12 июня 2019

Это описано в руководстве по проектированию для iPhone X. Теперь панель навигации содержит контроллер поиска.Вы можете создать экземпляр контроллера поиска и установить для него навигационный элемент.IarchController.Теперь он будет обрабатывать контроллер поиска во время вращения.

var search = UISearchController(searchResultsController: nil)
self.navigationItem.searchController = search
0 голосов
/ 11 июня 2019

Как указано в документации :

Хотя объект UISearchController является контроллером представления, вам следует никогда не представляйте это прямо из вашего интерфейса. Если вы хотите представить интерфейс результатов поиска явно, оберните ваш контроллер поиска в объекте UISearchContainerViewController и представить этот объект вместо этого.

Попробуйте обернуть UISearchController в UISearchContainerViewController.

0 голосов
/ 12 июня 2019

Как насчет сделать пользовательский вид, содержащий панель поиска.Сделайте это поверх слоев.

И когда произойдет поворот, обновите кадр / ограничения этого.

0 голосов
/ 10 июня 2019

Вы можете сделать это трик

class ViewController: UIViewController {

let sc = UISearchController(searchResultsController: nil)

override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = .white
    let button = UIButton(frame: CGRect(x: 20, y: 200, width: 100, height: 40))
    button.setTitle("Search", for: .normal)
    button.backgroundColor = .black
    button.addTarget(self, action: #selector(click), for: .touchUpInside)
    self.view.addSubview(button)


}

@objc func click(){
    self.present(sc, animated: true, completion: nil)
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

    var mFrame = sc.view.frame
    mFrame.origin.y = 5.0
    sc.view.frame = mFrame
}
...