1、布局适配方式

本文不讨论哪种布局适配方式最好,此处使用的是 Masonry 纯代码布局适配。(Masonry 底层就是 AutoLayout 的 NSLayoutConstraint)

2、iOS 方向枚举类

// 三维设备方向
typedef NS_ENUM(NSInteger, UIDeviceOrientation) {UIDeviceOrientationUnknown,UIDeviceOrientationPortrait,            // Device oriented vertically, home button on the bottomUIDeviceOrientationPortraitUpsideDown,  // Device oriented vertically, home button on the topUIDeviceOrientationLandscapeLeft,       // Device oriented horizontally, home button on the rightUIDeviceOrientationLandscapeRight,      // Device oriented horizontally, home button on the leftUIDeviceOrientationFaceUp,              // Device oriented flat, face upUIDeviceOrientationFaceDown             // Device oriented flat, face down
};// 二维界面方向
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {UIInterfaceOrientationUnknown            = UIDeviceOrientationUnknown,UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
};// iOS6 以后引入组合方式
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
};

获取设备方向:[[UIDevice currentDevice] orientation]
获取界面方向:[[UIApplication sharedApplication] statusBarOrientation]

3、iOS6 及其以上版本页面旋转设置方法

// 返回是否支持屏幕旋转
- (BOOL)shouldAutorotate
{return YES;
}// 返回支持的旋转方向
- (NSUInteger)supportedInterfaceOrientations
{  return UIInterfaceOrientationMaskAll;
}// 返回优先显示的屏幕方向,如果不设置,默认与进入前一个页面保持一致(注意该方法只对 ModalViewController 有效)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{  return UIInterfaceOrientationLandscapeLeft;
}

4、影响界面旋转特性的层级因素

(1)针对全局
Info.plist 文件中 Supported interface orientations 支持的方向。
(2)针对 Window
AppDelegate 中 supportedInterfaceOrientationsForWindow 支持的方向。
(3)针对单个页面
如果是 ChildrenViewController,则受限于其 RootViewController 中 shouldAutorotate 和 supportedInterfaceOrientations 支持的方向。(RootViewController 指 self.window.rootViewController 设置的那个 ViewController)
如果是 ModalViewController,则受限于其自身 shouldAutorotate 和 supportedInterfaceOrientations 支持的方向。(如果 ModalViewController 是经过包装的另一个 RootViewController,则与上述 ChildrenViewController 原理类似)
注意:上述三个层级因素最终的交集即为子视图控制器支持的旋转方向,如果交集为空,则会抛 UIApplicationInvalidInterfaceOrientationException 异常。

5、屏幕旋转机制流程

(1)加速计检测到方向变化,发出 UIDeviceOrientationDidChangeNotification 通知。
(2)程序接收到通知,通过 AppDelegate 知会当前程序的 Window。
(3)Window 通知 RootViewController,根据以下设置决定是否旋转。

  • Info.plist 中 Supported interface orientations 是否支持该方向
  • AppDelegate 中 supportedInterfaceOrientationsForWindow 中是否支持该方向
  • RootViewController 中 shouldAutorotate 是否为 YES
  • RootViewController 中 supportedInterfaceOrientations 是否支持该方向

(4)RootViewController 通知其 ChildrenViewController,同步旋转操作。
一般情况下 ChildrenViewController 不单独设置,与 RootViewController 保持一致。如果特殊场景需要单独设置,可以通过在 RootViewController 中下放权限,如:NavigationController 可以通过 self.topViewController 下放权限;TabBarController 可以通过 self.selectedViewController 下放权限。但是要注意,即使下放了权限,ChildrenViewController 还是必须遵守 Info.plist 和 AppDelegate 中的设置。
(5)如果存在弹出的 ModalViewController,则不受限于步骤4中的 RootViewController,只根据 Info.plist、AppDelegate 及其自身所支持的旋转设置决定是否旋转。如果 ModalViewController 是经过包装的另一个 RootViewController,则与步骤4原理类似。

6、产品开发中的应对策略。

(1)应用只需要支持单一方向。在 Info.plist 中锁死指定方向,限制屏幕旋转。
(2)应用统一支持多个方向自动旋转。在 Info.plist 中设置应用支持的方向,每个页面进行相应的自动旋转布局适配。
(3)应用不同页面支持的方向不一致。在 Info.plist 中设置所有页面支持的方向的并集,在 RootViewController 中将权限下放,由页面但与控制自己的旋转设置。

7、实际场景应用(有示例 Demo)

注意:本文不考虑 iOS6 以下版本的兼容性,所以下述 demo 只适配 iOS6 及其以上版本(只在 iOS7、iOS8 测试过)。下述场景处理方案中,iPad 默认支持四个方向,iPhone 默认支持 UIInterfaceOrientationMaskPortraitUpsideDown 三个方向。
(1)应用场景1:应用支持单一方向,限制旋转。(iPhone 中一般此方式用得比较多)
思路:在 Info.plist 中锁死指定方向,其他旋转设置均不用配置,适配方式比较多,也比较容易,不过建议纯代码的话还是通过 Masonry 进行布局适配。
示例:LimitPortraitDemo
(2)应用场景2:应用统一支持多方向自动旋转。(iPad 中一般此方式用得比较多)
思路:在 Info.plist 中设置应用支持的旋转方向即可,其他旋转设置均不用配置,布局要分别适配横屏与竖屏,纯代码的话建议通过 Masonry 进行布局适配。
示例:AnyRotationDemo
(3)应用场景3:应用支持单一方向,但是个别页面支持自动旋转。(一般不建议使用,除非特定场景,如视频播放器页面,自动旋转后横屏观看效果更好)
思路:在 Info.plist 中设置应用支持的所有旋转方向,在 RootViewController 中通过 shouldAutorotate 和 supportedInterfaceOrientations 锁死指定方向,然后在 ModalViewController 中通过 shouldAutorotate 和 supportedInterfaceOrientations 设置多个旋转方向,并进行相应的布局适配。适配方式纯代码的话同样建议 Masonry。
示例:SingleRotationDemo
(4)应用场景4:应用支持单一方向,但是个别页面支持手动控制旋转,不支持自动旋转。(一般不建议使用,除非特定场景,如视频播放器页面限制自动旋转,点击全屏按钮后横屏观看)
思路:有两种强制方式旋转方式,一种是带导航栏的,一种是不带导航栏的。具体实现思路示例中有详细描述。
示例:ForceRotationDemo

8、相关注意事项

  • 一般都不建议在程序里面直接调用 UIDeviceOrientation 的方向,而是用 UIInterfaceOrientation。
  • 获取屏幕方法,不要使用[[UIDevice curentDevice] orientation],建议使用[[UIApplication sharedApplication] statusBarOrientation]。
  • 如果 shouldAutorotate 返回 YES 的话,设置 setStatusBarOrientation 是不管用的。
  • 如果 shouldAutorotate 返回 NO 的话,[[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)] 方法是不管用的。
  • 尽量不要使用强制旋转的方式,通过 present 出 ModalViewController 方式,单独控制每个试图控制器的旋转设置。苹果官方也是支持这种方式。

【精】iOS6 及其以上版本自动旋转、手动强制旋转方案及布局适配相关推荐

  1. 微信小程序版本自动更新用户感知提示方案总结

    微信小程序版本自动更新用户感知提示方案总结 需求背景 最近基于uniapp开发微信小程序上线后,在迭代版本后期望自动更新提示. 使感知. 解决方案 使用全局唯一的对象: updateManager. ...

  2. android 系统(143)---Android实现App版本自动更新

    Android实现App版本自动更新 现在很多的App中都会有一个检查版本的功能.例如斗鱼TV App的设置界面下: 当我们点击检查更新的时候,就会向服务器发起版本检测的请求.一般的处理方式是:服务器 ...

  3. 手动制造报错_Windows 10驱动更新调整:不再自动安装“手动”驱动更新

    正如上月月底放出的公告,微软已经对 Windows 10 驱动更新进行了调整.虽然这项新调整的目的是为了改善整体体验,但在极少数情况下可能会给某些用户带来麻烦. 01 Windows 10驱动更新调整 ...

  4. 西门子HMI精智面板实现用户自动登陆

    西门子HMI精智面板实现用户自动登录 场景模拟 功能需求 实现流程 测试效果 案例程序 场景模拟 在实际生产环境中,为了保证账户密码的保密性和工作的方便,需要定时或者以按钮形式自动登录账号密码. 功能 ...

  5. Allegro 172版本自动放置层叠

    Allegro 172版本自动放置层叠 Allegro 172版本支持自动放置层叠,无需手动绘制,效果如下图 具体操作步骤如下 选择Manufacture-选择Cross Section Chart命 ...

  6. 自动判断浏览器的中英文版本自动跳转网站中英文页面代码

    许多网站现在都是依靠自动判断浏览器的中英文版本来判断给你打开网站的中文还是英文版,也许好多朋友还不知道这个代码,今天正好给公司改版企业网站用到了,在此公布出来,供大家一起学习. HTML网页根据来访者 ...

  7. SpringBoot集成Es使用ElasticSearchTemplate7.x版本自动注入失败解决

    SpringBoot集成Es使用ElasticSearchTemplate7.x版本自动注入失败解决 错误: Caused by: org.springframework.beans.factory. ...

  8. JS图片自动或者手动滚动效果(支持left或者up)

    JS图片自动或者手动滚动效果 在谈组件之前 来谈谈今天遇到搞笑的事情,今天上午接到一个杭州电话 0571-28001187 即说是杭州人民法院的 貌似说我用招商银行信用卡在今年的6月23日借了招商银行 ...

  9. python如何设置画布开始位置_如何设置亚马逊站内广告?亚马逊自动广告手动广告都在什么位置?...

    我做跨境电商也有六年的时间了,在电商这个行业也有自己的一些经验.经验也许没有其他大卖家丰富,但会将我知道的都进行分享.如果有不懂得亚马逊问题可以+我(V:772024802).我这里给大家安排一堂直播 ...

最新文章

  1. Paper:《Generating Sequences With Recurrent Neural Networks》的翻译和解读
  2. mysql分区跨机器_(转) mysql的分区技术 .
  3. 《每日一题》48. Rotate Image 旋转图像
  4. C#后台调用前台javascript的五种方法
  5. python5数据存储
  6. SpringBoot项目中,获取配置文件信息
  7. PHP 判断是否包含某字符串
  8. Unity3d AR 增强现实技术列表(2016年3月31日更新)
  9. 自定义按键_NS推送10.0.0版本更新 新增按键自定义和数据转移功能
  10. python人脸识别库教程_OpenCV-最优秀的Python人脸识别库安装及入门教程
  11. FORTRAN里的SCALE函数
  12. 【翻译】图解Janusgraph系列-事务详解(Janusgraph Transactions)
  13. unity怎么显示骨骼_Unity3d教程:骨骼动画介绍
  14. 个人注册网站域名怎么注册?能注册哪些?
  15. async的waterfall
  16. 智商黑洞(门萨Mensa测试)6
  17. mp4视频文件损坏的修复方法
  18. 我的天空是灰色的......
  19. STC89C52RC最小系统板
  20. 《真正的程序员不要使用PASCAL》

热门文章

  1. python人像绘制_用Python 代码实现简单图片人像识别换脸
  2. iMovie制作画中画特效
  3. QTreeView 设置背景色应用于整条
  4. 为AWS EC2实例添加固定IP
  5. ILRuntime foreach 存在GC
  6. WEB菜鸟笔记(一)
  7. 迪文智慧会议视频总线投屏方案新升级
  8. 操作系统之内存管理总结——进来背书
  9. win10取消开机密码方法
  10. css实现平行四边形等特殊形状 文字图片倾斜