UIDeviceOrientation与UIinterfaceOrientation以及屏幕旋转的方式

在日常开发过程中,经常会遇到转屏的需求,最近遇到一个转屏相关的bug,顺带着总结下iOS端实现转屏需要做的事情。


什么是设备方向,什么是视图方向



首先需要明确两个概念,设备方向(UIDeviceOrientation)和视图方向(UIInterfaceOrientation)


UIDeviceOrientation

不受锁定屏幕方向的影响,通过

[UIDevice currentDevice].orientation
客观反映出当前设备所处的方向,与视野中正在展示视图的方向无关,该属性只读,无法修改

该属性的变化可以通过监听UIDeviceOrientationDidChangeNotification来实时获得设备方向的变化


UIInterfaceOrientation

多数的旋转都需要通过旋转controller来实现。controller的方向也就是我上面提到的视图方向,使用该枚举UIInterfaceOrientation来表达。

如果想获得当前的视图方向,可以通过以下代码获得

[UIApplication sharedApplication].statusBarOrientation

视图方向的改变一定是由于设备方向发生了变化,设备方向的改变也只能是由于物理改变造成的。但是有一个例外,会在后面强制转屏部分详细说明。


如何让Controller随设备方向旋转



1. 配置App支持的视图方向

首先需要配置下当前App能支持的视图方向,所有使用的controller所能支持的视图方向是该配置的子集;

可以通过以下两种方法进行配置:


方法1,在Xcode选项中配置:

在Xcode->工程->General->Deployment Info中对Device Orientation进行配置,注意这里的Device Orientation不是上面所说的设备方向

UIDeviceOrientation与UIinterfaceOrientation以及屏幕旋转的方式_第1张图片


方法2,在AppDelegate中通过代码配置:

在AppDelegate中实现如下方法:

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return UIInterfaceOrientationMaskAll;
}

如果同时使用了两种方式,那第二种使用代码的方式会覆盖第一种在Xcode中配置的方式


2. 配置Controller支持的方向

代码很简单,表示当前Controller是否支持旋转,支持的方向都有什么,如下:

//是否支持转屏
- (BOOL)shouldAutorotate
{
    return YES;
}
//在支持转屏的前提下,返回具体支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

但是这段代码具体要写在哪个viewController中才有效果呢?

一个viewController是否可以旋转并不是由他自己决定的,而是由rootViewController或者最上层被present上来的viewController来决定的。

每个App都有一个rootViewController,如果没有通过present的方式推入controller,那么rootViewController支持的方向就决定了视图方向;

如果有通过present的方式推入controller,那么最近的一次present操作对应的controller就决定了视图方向;

以上的代码需要放在上面说到的决定了视图方向的controller中


还有一个回调方法,决定了viewController出现时的视图方向,该回调方法只对present方式进入界面的viewController有效果

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}


当然还有一点最重要的,记得要在下拉框中打开设备的转屏锁,要不然怎么转ViewController都不会跟着转的



关于强制转屏

在上文中提过,设备方向改变一定是由于物理改变造成的,其实这并不绝对

苹果的API曾经是允许修改[UIDevice currentDevice].orientation,后来这个接口被干掉作为私有API了

但是我们还是可以通过一些其他方式绕过苹果的限制来设置[UIDevice currentDevice].orientation,设备方向一旦改变,再符合上述视图方向改变的条件,视图方向就会被旋转,从而达到强制转屏的效果

在实际开发过程中也会遇到类似的场景,比如播放器的全屏操作,就是一次强制的视图方向改变

代码如下:

NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];


关于UINavigationController的旋转


其实道理是一样的,只不过如果present上来一个navigationController的时候,你需要想办法让这个navigationController去实现上述的shouldAutoRotate和supportedInterfaceOrientations方法,可以通过类别或继承重写的方式,这里也就不详述了


你可能感兴趣的:(iOS)