在iOS 8中处理方向变化的“正确”方法是什么?

有人可以告诉我在iOS 8中使用纵向和横向界面方向的“正确”或“最佳”方法吗? 看起来,我想用于这个目的的所有function都在iOS 8中被弃用,而且我的研究没有find清晰,优雅的select。 我真的应该看看宽度和高度来确定我自己,如果我们在纵向或横向模式?

例如,在我的视图控制器中,我应该如何实现下面的伪代码?

if we are rotating from portrait to landscape then do portrait things else if we are rotating from landscape to portrait then do landscape things 

苹果build议使用尺寸等级作为可用屏幕空间的粗略度量,以便您的用户界面可以显着改变其布局和外观。 考虑一下,纵向的iPad具有与横向相同的大小类别(常规宽度,常规高度)。 这意味着你的用户界面在两个方向上应该或多或less相似。

但是,在iPad中从纵向到横向的变化足够大,即使尺寸类别没有变化,您也可能需要对UI进行一些较小的调整。 由于UIViewController上与界面方向相关的方法已被废弃,Apple现在build议在UIViewController作为替代实现以下新方法:

 - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; // Code here will execute before the rotation begins. // Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:] [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { // Place code here to perform animations during the rotation. // You can pass nil or leave this block empty if not necessary. } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { // Code here will execute after the rotation has finished. // Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:] }]; } 

大! 现在,在旋转开始之前以及结束之后,您将获得callback。 但实际上知道旋转是纵向还是横向呢?

苹果build议只考虑父视图大小的变化。 换句话说,在从纵向到横向的iPad旋转过程中,您可以将其视为根级视图,只需将其范围bounds.size{768, 1024} bounds.size {768, 1024}更改为{1024, 768} 。 知道这一点之后,您应该使用传递给viewWillTransitionToSize:withTransitionCoordinator:方法的size来判断您是否旋转到纵向或横向。

如果你想要一个更加无缝的方式将遗留代码迁移到新的iOS 8方式,可以考虑在UIView上使用这个简单的类 ,它可以用来确定一个视图是基于它的“肖像”还是“风景”尺寸。

回顾一下:

  1. 您应该使用大小类来确定何时显示根本不同的用户界面(例如“类似iPhone的”用户界面与“类似iPad的”用户界面)
  2. 如果在大小类没有改变但是您的容器(父视图)大小,例如iPad旋转时,需要对UI进行较小的调整,请在UIViewController中使用viewWillTransitionToSize:withTransitionCoordinator: callback。
  3. 您的应用中的每个视图只应根据布局所在的空间进行布局决策。让视图的自然分层结构级联这些信息。
  4. 同样,不要使用statusBarOrientation – 这基本上是一个设备级别的属性 – 来确定是否布局“肖像”与“风景”的视图。 状态栏的方向应该只能被处理UIWindow的代码所使用,而UIWindow实际上就是在应用程序的根层。

我只是使用通知中心:

添加一个方向variables(将在最后解释)

 //Above viewdidload var orientations:UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation 

出现视图时添加通知

 override func viewDidAppear(animated: Bool) { NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: nil) } 

视图消失时移除通知

 override func viewWillDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil) } 

触发通知时获取当前的方向

 func orientationChanged (notification: NSNotification) { adjustViewsForOrientation(UIApplication.sharedApplication().statusBarOrientation) } 

检查方向(纵向/横向)并处理事件

 func adjustViewsForOrientation(orientation: UIInterfaceOrientation) { if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown) { if(orientation != orientations) { println("Portrait") //Do Rotation stuff here orientations = orientation } } else if (orientation == UIInterfaceOrientation.LandscapeLeft || orientation == UIInterfaceOrientation.LandscapeRight) { if(orientation != orientations) { println("Landscape") //Do Rotation stuff here orientations = orientation } } } 

我添加一个方向variables的原因是,当在一个物理设备上进行testing时,方向通知在设备中的每一个小动作中被调用,而不是在它旋转时被调用。 如果var和if语句切换到相反的方向,只会调用代码。

基于smileyborg非常详细(并接受)的答案,这里是一个适应使用swift 3:

 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: nil, completion: { _ in self.collectionView.collectionViewLayout.invalidateLayout() }) } 

而在UICollectionViewDelegateFlowLayout实现中,

 public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { // retrieve the updated bounds let itemWidth = collectionView.bounds.width let itemHeight = collectionView.bounds.height // do whatever you need to do to adapt to the new size } 

从用户界面的angular度来看,我相信使用大小类是Apple推荐的方法来处理不同方向,大小和规模的界面。

请参阅以下部分: 特性描述界面的大小类和缩放比例 : https : //developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html

“iOS 8增加了新的function,使得处理屏幕尺寸和方向更加灵活。”

这也是一个很好的文章: https : //carpeaqua.com/thinking-in-terms-of-ios-8-size-classes/

编辑更新链接: https ://carpeaqua.com/2014/06/14/thinking-in-terms-of-ios-8-size-classes/(Credit:Koen)