【精】iOS6 及其以上版本号自己主动旋转、手动强制旋转方案及布局适配
1、布局适配方式
本文不讨论哪种布局适配方式最好。此处使用的是 Masonry 纯代码布局适配。
(Masonry 底层就是 AutoLayout 的 NSLayoutConstraint)
2、iOS 方向枚举类
// 三维设备方向
typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom
UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top
UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right
UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left
UIDeviceOrientationFaceUp, // Device oriented flat, face up
UIDeviceOrientationFaceDown // 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 中锁死指定方向,其它旋转设置均不用配置。适配方式比較多,也比較easy,只是建议纯代码的话还是通过 Masonry 进行布局适配。
演示样例:LimitPortraitDemo
(2)应用场景2:应用统一支持多方向自己主动旋转。(iPad 中一般此方式用得比較多)
思路:在 Info.plist 中设置应用支持的旋转方向就可以。其它旋转设置均不用配置。布局要分别适配横屏与竖屏,纯代码的话建议通过 Masonry 进行布局适配。
演示样例:AnyRotationDemo
(3)应用场景3:应用支持单一方向。可是个别页面支持自己主动旋转。(一般不建议使用,除非特定场景,如视频播放器页面,自己主动旋转后横屏观看效果更好)
思路:在 Info.plist 中设置应用支持的全部旋转方向。在 RootViewController 中通过 shouldAutorotate 和 supportedInterfaceOrientations 锁死指定方向。然后在 ModalViewController 中通过 shouldAutorotate 和 supportedInterfaceOrientations 设置多个旋转方向。并进行对应的布局适配。
适配方式纯代码的话相同建议 Masonry。
演示样例:SingleRotationDemo
(4)应用场景4:应用支持单一方向,可是个别页面支持手动控制旋转。不支持自己主动旋转。(一般不建议使用,除非特定场景。如视频播放器页面限制自己主动旋转,点击全屏button后横屏观看)
思路:有两种强制方式旋转方式,一种是带导航栏的,一种是不带导航栏的。具体实现思路演示样例中有具体描写叙述。
演示样例:ForceRotationDemo
8、相关注意事项
- 一般都不建议在程序里面直接调用 UIDeviceOrientation 的方向,而是用 UIInterfaceOrientation。
- 获取屏幕方法,不要使用[[UIDevice curentDevice] orientation],建议使用[[UIApplication sharedApplication] statusBarOrientation]。
- 假设 shouldAutorotate 返回 YES 的话,设置 setStatusBarOrientation 是无论用的。
- 假设 shouldAutorotate 返回 NO 的话,[[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)] 方法是无论用的。
- 尽量不要使用强制旋转的方式。通过 present 出 ModalViewController 方式。单独控制每一个试图控制器的旋转设置。
苹果官方也是支持这样的方式。
【精】iOS6 及其以上版本号自己主动旋转、手动强制旋转方案及布局适配的更多相关文章
- iOS两个强制旋转屏幕的方法
第一个: // 状态栏动画持续时间 CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimation ...
- 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)
在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...
- 【c语言】输入一个递增排序的数组的一个旋转,输出旋转数组中的最小元素
//旋转数组的最小数字 //题目:把一个数组最開始的若干个元素搬到数组的末尾.我们称之为数组的旋转. //输入一个递增排序的数组的一个旋转.输出旋转数组中的最小元素. //比如:数组{3.4,5,1, ...
- cocos2dx——lua自己主动和手动绑定
[自己主动绑定] 參考:http://my.oschina.net/skyhacker2/blog/298397 主要是通过引擎自带的tools/tolua,主要过程例如以下: 1.编写好要导出的c+ ...
- [NOIP]2017列队——旋转treap/非旋转treap
Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia所在的方阵中有n × m名学生,方阵的行数为 n,列数为m. 为了便 ...
- 头像修改功能 包含ios旋转图片 但是旋转后没遮罩, 正常图片可以显示遮罩 宽高不规则图片没做控制 遮罩框可以拖动
https://blog.csdn.net/wk767113154/article/details/77989544 参考资料 <template> <div id="p ...
- Unity3D研究院之设置自动旋转屏幕默认旋转方向
如下图所示,在处理屏幕默认旋转方向的时候可以在这里进行选择,上下左右一共是4个方向. 策划的需求是游戏采用横屏,但是要求支持两个方向自动旋转,如下图所示,我的设置是这样的. Default Orien ...
- 2D旋转和3D旋转
2D旋转 先给个容器 <p onClick="rotate2D()" id="rotate2D" class="animated_div&quo ...
- MSSQL旋转和反旋转的例子
1.旋转 ;WITH CTE AS ( AS VAL UNION ALL UNION ALL UNION ALL UNION ALL UNION ALL UNION ALL UNION ALL ) S ...
随机推荐
- Python并发编程-守护进程
守护进程 子进程转换为守护进程 主进程的代码结束,子进程的代码也应该接收, 这个事情有守护进程来做 守护进程会随着主进程的代码执行完毕而结束, 而不是随着主进程的接收而结束(子进程不一定结束) fro ...
- CentOS使用
centos7编译安装git最新版 CentOS下 pycharm开发环境搭建之无穷无尽的问题 CentOS 7入门操作基础教程 centos中文站 CentOS7 常用命令集合 centos中有vi ...
- Spring框架中ModelAndView、Model、ModelMap区别 (转)
原文地址:http://www.cnblogs.com/google4y/p/3421017.html SPRING框架中ModelAndView.Model.ModelMap区别 注意:如果方法 ...
- Bzoj2002/洛谷P3203 [HNOI2010]弹飞绵羊(分块)
题面 Bzoj 洛谷 题解 大力分块,分块大小\(\sqrt n\),对于每一个元素记一下跳多少次能跳到下一个块,以及跳到下一个块的哪个位置,修改的时候时候只需要更新元素所在的那一块即可,然后询问也是 ...
- 【最短路径】 SPFA算法优化
首先先明确一个问题,SPFA是什么?(不会看什么看,一边学去,传送门),SPFA是bellman-ford的队列优化版本,只有在国内才流行SPFA这个名字,大多数人就只知道SPFA就是一个顶尖的高效算 ...
- 【2-SAT】【DFS】【分类讨论】Gym - 101617K - Unsatisfying
题意:给你一张2-SAT,问你加至少几句a V b(不能用非运算)这样的语句,使得其无法全为真. 如果最开始没有左右两项都含非运算的析取表达式,则无解,因为显然你可以对每一项的不含非的那项规定为真,使 ...
- UI/GUI/UE/UX/ID/UED/UCD的区别
简述: UI (User Interface):用户界面 UE (User Experience):用户体验 ID (Interaction design):交互设计 UID (User Interf ...
- Java乐观锁实现之CAS操作
介绍CAS操作前,我们先简单看一下乐观锁 与 悲观锁这两个常见的锁概念. 悲观锁: 从Java多线程角度,存在着“可见性.原子性.有序性”三个问题,悲观锁就是假设在实际情况中存在着多线程对同一共享的竞 ...
- 编写Shell脚本(未完待续)
Shell脚本命令的工作方式有两种:交互式批处理 交互式:用户每输入一条命令就立即执行 批处理:由用户事先编写好一个完整的Shell脚本,Shell会一次性执行脚本中诸多命令
- Linux下简单分析请求有没有进到本机的工具tcpdump(网络接口的数据包的头信息)
可以通过这个工具快速分析出一个请求到底有没有进入到本机.信息有点简单,对于前期的分析比较有帮助.而对于详细的分析可以借助iptables的raw表进行日志分析. 参考: http://man.linu ...