如何在屏幕方向改变后获取屏幕高度?

4

在方向更改后查询UIScreen.main.bounds.height时,我得到了一些奇怪的结果。也许这不是正确的方法。

我有一个观察者监听NSNotification.Name.UIDeviceOrientationDidChange事件:

NotificationCenter.default.addObserver(self, selector: #selector(self.orientationChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

这将调用一个函数,将限制设置为新屏幕高度的75%。在iPhone上运行良好,但iPad返回错误的屏幕高度。

如果iPad处于横向方向,则UIScreen.main.bounds.height将返回与纵向方向中的高度相同的值,反之亦然。

func orientationChange() {
    // This will print the correct value on iPhone and iPad.
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }

    let screenSize = UIScreen.main.bounds
    let screenHeight = screenSize.height
    self.searchViewHeightConstraint.constant = screenHeight * 0.75

    // Correct value on iPhone. Incorrect on iPad.
    print("screenHeight: '\(screenHeight)'") 

    UIView.animate(withDuration: 0.6, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
        self.searchView.superview?.layoutIfNeeded()
    }, completion: nil)
}

我也遇到了 viewWilltransition 方法来监测屏幕方向的变化,但是这个方法与上面的方法完全相反。例如,在iPad上高度正确,在iPhone上则不正确:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    let screenSize = UIScreen.main.bounds
    let screenHeight = screenSize.height
    self.searchViewHeightConstraint.constant = screenHeight * 0.75

    // Correct value on iPad. Incorrect on iPhone.
    print("screenHeight: '\(screenHeight)'") 
}

这种不一致的行为在 iPhone 和 iPad 之间出现的原因是什么?使用 NotificationCenter 监测方向变化是否正确?

你得到的 screenHeight 值是更大还是更小? - Srdjan
停止使用screensize = UIScreen.main.bounds,改用size,该方法已经为您提供。您可以执行size.height * 0.75。 - ExtremeSuspense
另外,如果您正在使用约束,并且您的searchView等于视图的高度,则在相同的heighViewConstraint上,如果它始终是该大小,则可以将修改器设置为0.75。然后,当旋转视图时,视图将自动更新,您无需执行任何逻辑。 - ExtremeSuspense
3个回答

4
你应该使用 viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)。这将给你大小,并且比使用通知可靠得多。
此外,如果你想要做动画,在 UIViewControllerTransitionCoordinator 内部,你可以利用方法 animate(alongsideTransition animation: ((UIViewControllerTransitionCoordinatorContext) -> Swift.Void)?, completion: ((UIViewControllerTransitionCoordinatorContext) -> Swift.Void)? = nil) -> Bool

我已经尝试过这个方法,但它的行为与我的问题描述相反。也就是说,在iPad上它报告了正确的尺寸,但在iPhone上却报告了错误的尺寸。 - Turnip
你尝试过使用animate(alongsideTransition...)吗?我用过这个方法,在完成后一切似乎都恰到好处了。 - ExtremeSuspense
所以当我创建了一个测试项目并打印出iPhone的尺寸时,我得到了:横屏(736.0,414.0)竖屏(414.0,736.0),然后对于iPad,我得到了横屏(1024.0,768.0)竖屏(768.0,1024.0)。这些是iPad Air 2和iPhone 8。 - ExtremeSuspense
1
你关于 viewWillTransition 的说法是正确的。我应该使用 size 参数而不是查询 UIScreen 的边界。非常感谢。 - Turnip

4

您需要使用:

dispatch_async(dispatch_get_main_queue()) { 
println("h:\(view.bounds.size.height)")
println("w:\(view.frame.size.width)")
         }

// 所有需要在 dispatch_async 下编写的代码

此代码将在旋转完成后(在主队列中)执行,并且新大小可用。


DispatchQueue.main.async { print("你好") }在 Swift 3/4 中 - mossman252

1
在Swift 2.3中,这对于iPad和iPhone都适用。
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    print(size.height)

  if UIDevice.currentDevice().orientation.isLandscape {
     print("Landscape")
     print(size.height)

  } 
 else {
      print("Portrait")
      print(size.height)
     }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接