viewWillTransition дает неправильный размер

Я делаю пользовательскую клавиатуру. Я хочу сгенерировать ширину и высоту ключей (UIButtons) на основе ширины и высоты представления.

Когда клавиатура загружена изначально, viewDidAppear правильно определяет высоту представления. (375 х 216)

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

При повороте в альбомную ориентацию он вызывает viewWillTransition

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

    NSLog("toSize \(size.width) x \(size.height)")

    coordinator.animate(alongsideTransition: {(_ context: UIViewControllerTransitionCoordinatorContext) -> Void in
        NSLog("animating \(self.view.frame.width) x  \(self.view.frame.height)")

    }, completion: {(_ context: UIViewControllerTransitionCoordinatorContext) -> Void in

        NSLog("animationCompleted \(self.view.frame.width) x  \(self.view.frame.height)")
        self.renderKeys()
    })

}

Возвращаясь к Портрету, получим это

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

Вот отладочный журнал по порядку.

[28651:1348399] Calling viewDidAppear

[28651:1348399] Cleaning keys
[28651:1348399] toSize 667.0 x 216.0
[28651:1348399] animating 667.0 x  216.0
[28651:1348399] animationCompleted 667.0 x  216.0

[28651:1348399] Cleaning keys
[28651:1348399] toSize 375.0 x 162.0
[28651:1348399] animating 375.0 x  162.0
[28651:1348399] animationCompleted 375.0 x  162.0

1 ответ

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

После нескольких часов экспериментов я узнал следующее:

  • Когда вы запускаете клавиатуру как приложение, представления загружаются только один раз, и жизненный цикл приложения завершается, как и ожидалось (application(didFinishLaunchingWithOptions:), applicationDidBecomeActiveи т. д.)
  • Все ориентационные переходы могут быть зафиксированы в viewWillTransition(to size:), например, в iPhone 8+ размер отчета будет равен (414.0, 736.0) или (736.0, 414.0)

Теперь, запустив проект в качестве цели клавиатуры: -

  • Система не соответствует обычному жизненному циклу приложения:application(didFinishLaunchingWithOptions:),applicationDidBecomeActiveи т.д. не сообщается
    • Каждый раз, когда устройство меняется с вертикального на горизонтальное или наоборот, основной ViewController загружен.
    • Попытка захватить viewSize в viewDidLoad может быть сложно, учитывая, что вам может потребоваться задержка (используяTimer.scheduledTimer(withTimeInterval:)по крайней мере в первой итерации
    • ViewSize сообщается в updateViewConstraints(), но размер кажется не совсем надежным. После каждого перехода в книжный режим он может сообщать о размере 414 x 736 (размер экрана) или 414 x 226 (правильный размер клавиатуры). В случае iPhone 8+
    • Учитывая это конкретное управление жизненным циклом приложения, viewWillTransition Метод не выполняется при переходе от Портрета к Пейзажу или от Пейзажа к Портрету (я полагаю, это связано с жизненным циклом вида, который прерывается при каждом повороте).
    • Он выполняется при переходе от LandscapeLeft к LandscapeRight (через UpsideDown, который не включен) и сообщает правильный размер (736 x 162 в iPhone 8+)

Итак, что я делаю, чтобы захватить размер экрана в viewDidLoad после задержки и забыть о updateViewConstraints или же viewWillTransition(to size:)

Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false) { (nil) in
    print("Load Size: \(self.view.frame.size)")
}

ПРИМЕЧАНИЕ * Эта задержка, по-видимому, необходима только при первой загрузке (в этом случае даже updateViewConstraints выполняется раньше viewDidLoad, В следующих итерациях viewDidLoad это не требуется. Также. Вы можете поэкспериментировать с задержкой и протестировать на реальных устройствах против симулятора

Справочная таблица:

Устройство - (Экран) - (KeyboardPortrait) - (KeyboardLandscape)

iPhone X - (375 x 812) - (375 x 141) - (662 x 131)

iPhone 8+ - (414 x 736) - (414 x 226) - (736 x 162)

iPhone 7 + / 8 + - (414 x 736) - (414 x 226) - (736 x 162)

iPhone 7/8 - (375 x 667) - (375 x 216) - (667 x 162)

6 / 6s / 6 + / 6s + - То же, что iPhone 7/8

iPhone SE - (320 x 568) - (320 x 216) - (568 x 162)

Я надеюсь, что это помогает. С уважением... е

Другие вопросы по тегам