iOS 屏幕旋转的实践解析

屏幕旋转是在视频直播类 App 中常见的场景,在即构科技之前发布的 Roomkit SDK 中也有屏幕跟随手机自动旋转的场景 。
 
在 Roomkit SDK 自身开发和客户接入的过程中我们也会发现,实现屏幕旋转的需求往往没有那么顺利,经常会出现无法旋转、旋转后布局适配等问题 。
 
本篇文章根据我们以往的开发经验整理了屏幕旋转实现的相关实践方法 , 解析在实现过程中遇到的常见问题 。
 
一、快速实现旋转 
IOS 屏幕旋转的实现涉及到一堆枚举值和回调方法,对于没有做过旋转相关需求的开发来说,可能一上来就晕了,所以我们先动手,让屏幕转起来吧 。
 
实现旋转的方式主要有两种,跟随手机感应旋转和手动旋转 , 接下来对这两种方式进行逐一介绍 。
 
方式一:跟随手机感应器旋转要实现自动跟随手机旋转,首先要让当前的视图控制器实现以下三个方法:
 
 
/// 是否自动旋转- (BOOL)shouldAutorotate {return YES;}/// 当前 VC支持的屏幕方向- (UIInterfaceOrientationMask)supportedInterfaceOrientations {return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortrAIt | UIInterfaceOrientationMaskLandscapeLeft;}/// 优先的屏幕方向- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {return UIInterfaceOrientationPortrait;} 
 
这种方法需要注意以下几点:
 

  • shouldAutorotate 返回 YES 表示跟随系统旋转,但是受 supportedInterfaceOrientations 方法的返回值影响,只支持跟随手机传感器旋转到支持的方向 。
  • preferredInterfaceOrientationForPresentation 需要返回 supportedInterfaceOrientations中支持的方向 , 不然会发生 'UIApplicationInvalidInterfaceOrientation'崩溃 。
 
方式二:手动旋转这种方式在很多视频软件中都很常见,点击按钮后旋转至横屏 。
 
这时需要在 shouldAutorotate 中返回 yes,然后再在此方法中 UIInterfaceOrientation 传入你需要旋转到的方向 。注意这是私有方法 , 是否使用请自行斟酌 。
 
- (void)changeVCToOrientation:(UIInterfaceOrientation)orientation {if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {SEL selector = NSSelectorFromString(@"setOrientation:");NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];[invocation setSelector:selector];[invocation setTarget:[UIDevice currentDevice]];int val = orientation;[invocation setArgument:&val atIndex:2];[invocation invoke];}} 
场景应用自动旋转如果你的 iphone 没有关闭系统屏幕旋转,你就能发现系统相册 APP 的页面是可以跟着手机转动方向旋转的 。
 
如果你想实现和它一样的效果,只需要按照前面方式一(跟随手机感应器旋转)去配置你的视图控制器的方法,之后控制器就可以在 supportedInterfaceOrientations 返回的方向内实现自由旋转了 。
 
只能手动旋转这种场景比较少见,在视频直播类 APP 中常见的场景是自动和手动旋转相结合的方式 。
 
如果你要实现只能通过像点击按钮去旋转的方式 , 首先需要在 supportedInterfaceOrientations 方法中返回你需要支持的方向 , 这里重点是shouldAutorotate 方法的返回值 。
 
上面方式二中(手动旋转)说明了手动旋转需要 shouldAutorotate 返回 YES,但是这也会让控制器支持自动旋转,不符合这个需求,所以我们按以下方法处理:
 
 
 
- (BOOL)shouldAutorotate {if (self.isRotationNeeded) {return YES;} else {return NO;}} 
 
属性 isRotationNeeded 作为是否需要旋转的标记 , isRotationNeeded 默认为 NO,此时就算你旋转设备,回调 shouldAutorotate 方法时也不会返回 YES,所以屏幕也不会自动旋转 。
 
【iOS 屏幕旋转的实践解析】剩下的只需要你在点击旋转的按钮后将 isRotationNeeded 置为 YES 并调用手动旋转的方法 , 这样处理后只能手动旋转的效果就实现了 。
 
二、旋转后的 UI 布局更新 
通常情况下,应用旋转到横竖屏后,因为不同的宽高比会有不同 UI,所以在屏幕旋转的场景中我们又需要解决旋转后 UI 适配的问题 。
 
手机旋转时,正常情况下若 shouldAutorotate 返回 YES , 当视图控制器需要旋转就会触发 viewWillTransitionToSize 方法,这样我们就找到了去更新横竖屏 UI 的时机了,也就是在 completion block 里去完成旋转后的适配逻辑 。


推荐阅读