2

我正在制作一个自定义键盘。我想根据视图的宽度和高度生成键(UIButtons)的宽度和高度。

最初加载键盘时,viewDidAppear 正确确定了视图的高度。(375 x 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
4

1 回答 1

4

我也在使用自定义键盘,发现了类似的问题。

经过几个小时的实验,我学到了以下内容:

  • 当您将键盘作为应用程序运行时,视图仅加载一次,并且应用程序生命周期按预期完成(application(didFinishLaunchingWithOptions:), applicationDidBecomeActive)等执行)
  • 所有方向转换都可以在viewWillTransition(to size:). 例如,在 iPhone 8+ 中,这将报告 (414.0, 736.0) 或 (736.0, 414.0) 的大小

现在,将项目作为键盘目标运行: -

  • 系统不遵循常规的app生命周期:) application(didFinishLaunchingWithOptions:, applicationDidBecomeActive等不报
    • 每次设备从垂直变为水平或反之亦然时,ViewController都会加载主设备。
    • 尝试捕获 viewSizeviewDidLoad可能会很棘手,因为您可能需要延迟( Timer.scheduledTimer(withTimeInterval:)至少在第一次迭代中使用
    • viewSize 在 中报告updateViewConstraints(),但大小似乎并不完全可靠。每次转换为纵向后,它可以报告大小为 414 x 736(屏幕大小)或 414 x 226(正确的键盘大小)。如果是 iPhone 8+
    • 鉴于应用程序生命周期的这种特殊管理,viewWillTransition从纵向到横向或从横向到纵向时不会执行该方法(我想这与每次旋转中中断的视图生命周期有关)。
    • 它在从 LandscapeLeft 到 LandscapeRight 时执行(通过 UpsideDown,未启用),它报告正确的尺寸(在 iPhone 8+ 中为 736 x 162)

所以,我正在做的是在viewDidLoad延迟后捕获屏幕尺寸并忘记updateViewConstraintsviewWillTransition(to size:)

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

注意*这个延迟似乎只在第一次加载时需要(在这种情况下,甚至updateViewConstraints在之前执行viewDidLoad。在 viewDidLoad 的以下迭代中,它不是必需的。另外。您可能想要试验延迟,并在实际设备中进行测试与模拟器对比

参考表:

设备 - (屏幕) - (键盘纵向) - (键盘横向)

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)

我希望它有所帮助。问候... e

于 2018-03-22T19:49:54.587 回答