什么是"权利"在iOS 8中处理方向更改的方法?

时间:2014-09-26 23:53:37

标签: ios ios8 orientation uiinterfaceorientation landscape-portrait

有人可以告诉我"对"或者"最好的"在iOS 8中使用纵向和横向界面方向的方法?似乎我想要用于此目的的所有功能都在iOS 8中被弃用,而我的研究似乎没有明确,优雅的替代方案。如果我们处于纵向或横向模式,我真的应该考虑宽度和高度来确定自己吗?

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

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

4 个答案:

答案 0 :(得分:250)

Apple建议使用大小类作为可用屏幕空间大小的粗略度量,以便您的UI可以显着改变其布局和外观。考虑到纵向的iPad具有与横向相同的尺寸等级(常规宽度,常规高度)。这意味着您的UI在两个方向之间应该或多或少相似。

然而,iPad中从纵向到横向的变化非常重要,即使尺寸类没有改变,您也可能需要对UI进行一些较小的调整。由于UIViewController上与界面方向相关的方法已被弃用,Apple现在建议在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:]

    }];
}

大!现在你在旋转开始之前以及完成之后得到回调。但实际上知道旋转是纵向还是横向呢?

Apple建议将轮换视为父视图大小的更改。换句话说,在iPad从纵向旋转到横向旋转期间,您可以将其视为根级视图,只需将其bounds.size{768, 1024}更改为{1024, 768}即可。知道了这一点,你应该使用上面传递给size方法的viewWillTransitionToSize:withTransitionCoordinator:来判断你是否正在转向纵向或横向。

如果您想要一种更加无缝的方式将旧代码迁移到新的iOS 8工作方式,请考虑在UIView上使用this simple category,这可用于确定视图是“纵向”还是“景观“基于它的大小。

回顾一下:

  1. 您应该使用尺寸类来确定何时显示根本不同的UI(例如“类似iPhone的”UI与“类似iPad的”UI)
  2. 如果您需要在尺寸类更改但您的容器(父视图)尺寸更改时(例如iPad旋转时)对您的UI进行较小的调整,请使用{{1} UIViewController中的回调。
  3. 应用中的每个视图都应该根据布局给出的空间做出布局决策。让视图的自然层次结构将此信息级联下来。
  4. 同样,不要使用viewWillTransitionToSize:withTransitionCoordinator: - 基本上是设备级属性 - 来确定是否为“肖像”与“横向”布局视图。状态栏方向只应由处理实际位于应用程序根目录的statusBarOrientation之类的代码使用。

答案 1 :(得分:15)

基于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
}

答案 2 :(得分:11)

我只是使用通知中心:

添加方向变量(将在最后解释)

//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
        }
    }
}

我添加方向变量的原因是因为在物理设备上进行测试时,会在设备中的每次轻微移动时调用方向通知,而不仅仅是在旋转时。添加var和if语句只会在代码切换到相反方向时调用代码。

答案 3 :(得分:2)

从UI的角度来看,我认为使用Size Classes是Apple推荐的处理不同方向,大小和规模的界面的方法。

请参阅以下部分: Traits描述接口的大小等级和比例https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html

  

&#34; iOS 8增加了新功能,使处理屏幕尺寸和方向更加通用。&#34;

这篇文章也是一篇好文章: 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/(图片来源:Koen)