一、两种orientation

了解屏幕旋转首先需要区分两种orientation

1、device orientation

设备的物理方向,由类型UIDeviceOrientation表示,当前设备方向获取方式:

1
[UIDevice currentDevice].orientation 

该属性的值一般是与当前设备方向保持一致的,但须注意以下几点:

①文档中对该属性的注释:

1
@property(nonatomic,readonly) UIDeviceOrientation orientation; // return current device orientation. this will return UIDeviceOrientationUnknown unless device orientation notifications are being generated. 

所以更推荐下面这种用法:

1
2
3
4
5
6 7 
if (![UIDevice currentDevice].generatesDeviceOrientationNotifications) {  [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];  } NSLog(@"%d",[UIDevice currentDevice].orientation);  [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; 

②系统横竖屏开关关闭时

如果关闭了系统的横竖屏切换开关,即系统层级只允许竖屏时,再通过上述方式获取到的设备方向将永远是UIDeviceOrientationUnknown。可以通过Core Motion中的CMMotionManager来获取当前设备方向。

2、interface orientation

界面显示的方向,由类型UIInterfaceOrientation表示。当前界面显示方向有以下两种方式获取:

1
2
NSLog(@"%d",[UIApplication sharedApplication].statusBarOrientation); NSLog(@"%d",viewController.interfaceOrientation); 

即可以通过系统statusBar的方向或者viewController的方向来获取当前界面方向。

3、二者区别

通过UIDevice获取到的设备方向在手机旋转时是实时的,通过UIApplication的statusBar或者viewController获取到的界面方向在下述方法:

1
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration: 

调用以后才会被更改成最新的值。

二、相关枚举定义

1、UIDeviceOrientation:

1
2
3
4
5
6 7 8 9 
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 }; 

2、UIInterfaceOrientation:

1
2
3
4
5
6 7 
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {  UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,  UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,  UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,  UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,  UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft }; 

从宏定义可知,device方向比interface多了两个定义:UIDeviceOrientationFaceUpUIDeviceOrientationFaceDown,分别表示手机水平放置,屏幕向上和屏幕向下。

三、相关方法

1、iOS5中控制屏幕旋转的方法:

1
2
// Applications should use supportedInterfaceOrientations and/or shouldAutorotate..
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation NS_DEPRECATED_IOS(2_0, 6_0); 

如果打算支持toInterfaceOrientation对应的方向就返回YES,否则返回NO。

2、iOS6中控制屏幕旋转相关方法:

1
2
3
4
5
// New Autorotation support.
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0); - (NSUInteger)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0); // Returns interface orientation masks. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0); 

第一个方法决定是否支持多方向旋转屏,如果返回NO则后面的两个方法都不会再被调用,而且只会支持默认的UIInterfaceOrientationMaskPortrait方向;

第二个方法直接返回支持的旋转方向,该方法在iPad上的默认返回值是UIInterfaceOrientationMaskAll,iPhone上的默认返回值是UIInterfaceOrientationMaskAllButUpsideDown,详情见官方Q&A文档;

第三个方法返回最优先显示的屏幕方向,比如同时支持Portrait和Landscape方向,但想优先显示Landscape方向,那软件启动的时候就会先显示Landscape,在手机切换旋转方向的时候仍然可以在Portrait和Landscape之间切换;

3、attemptRotationToDeviceOrientation方法

从iOS5开始有了这个新方法:

1
2
3
// call this method when your return value from shouldAutorotateToInterfaceOrientation: changes
// if the current interface orientation does not match the current device orientation, a rotation may occur provided all relevant view controllers now return YES from shouldAutorotateToInterfaceOrientation:
+ (void)attemptRotationToDeviceOrientation NS_AVAILABLE_IOS(5_0); 

该方法的使用场景是interface orientation和device orientation不一致,但希望通过重新指定interface orientation的值,立即实现二者一致;如果这时只是更改了支持的interface orientation的值,没有调用attemptRotationToDeviceOrientation,那么下次device orientation变化的时候才会实现二者一致,关键点在于能不能立即实现。

举个例子:

假设当前的interface orientation只支持Portrait,如果device orientation变成Landscape,那么interface orientation仍然显示Portrait;

如果这时我们希望interface orientation也变成和device orientation一致的Landscape,以iOS6为例,需要先将supportedInterfaceOrientations的返回值改成Landscape,然后调用attemptRotationToDeviceOrientation方法,系统会重新询问支持的interface orientation,已达到立即更改当前interface orientation的目的。

四、如何决定interface orientation

1、全局控制

Info.plist文件中,有一个Supported interface orientations,可以配置整个应用的屏幕方向,此处为全局控制。

2、UIWindow

iOS6的UIApplicationDelegate提供了下述方法,能够指定 UIWindow 中的界面的屏幕方向:

1
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window NS_AVAILABLE_IOS(6_0); 

该方法默认值为Info.plist中配置的Supported interface orientations项的值。

iOS中通常只有一个window,所以此处的控制也可以视为全局控制。

3、controller

只有以下两种情况:

  • 当前controller是window的rootViewController
  • 当前controller是modal模式的

时,orientations相关方法才会起作用(才会被调用),当前controller及其所有的childViewController都在此作用范围内。

4、最终支持的屏幕方向

前面所述的3种控制规则的交集就是一个controller的最终支持的方向;

如果最终的交集为空,在iOS6以后会抛出UIApplicationInvalidInterfaceOrientationException崩溃异常。

四、强制屏幕旋转

如果interface和device方向不一样,想强制将interface旋转成device的方向,可以通过attemptRotationToDeviceOrientation实现,但是如果想将interface强制旋转成任一指定方向,该方式就无能为力了。

不过聪明的开发者们总能想到解决方式:

1、私有方法

1
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 

但是现在苹果已经将该方法私有化了,越狱开发的同学可以试试,或者自己想法子骗过苹果审核吧。

2、旋转view的transform

也可以通过旋转view的transform属性达到强制旋转屏幕方向的目的,但个人感觉这不是靠谱的思路,可能会带来某些诡异的问题。

3、主动触发orientation机制

要是能主动触发系统的orientation机制,调用orientation相关方法,使新设置的orientation值起作用就好了。这样只要提前设置好想要支持的orientation,然后主动触发orientation机制,便能实现将interface orientation旋转至任意方向的目的。

万能的stackoverflow上提供了一种主动触发的方式:

在iOS4和iOS6以后:

1
2
3
4
UIViewController *vc = [[UIViewController alloc]init]; [self presentModalViewController:vc animated:NO]; [self dismissModalViewControllerAnimated:NO]; [vc release]; 

iOS5中:

1
2
3
4
UIWindow *window = [[UIApplication sharedApplication] keyWindow]; UIView *view = [window.subviews objectAtIndex:0]; [view removeFromSuperview]; [window addSubview:view]; 

这种方式会触发UIKit重新调用controller的orientation相关方法,以达到在device方向不变的情况下改变interface方向的目的。

虽然不优雅,但却能解决问题,凑合吧。。

PS:

话说iOS8中的屏幕旋转相关方法又变化了,表示适配起来很蛋疼。。。

五、参考文档

  • Why won’t my UIViewController rotate with the device?;
  • How to force a UIViewController to Portait orientation in iOS 6
  • IOS Orientation, 想怎么转就怎么转
  • iOS 屏幕方向那点事儿

转自:http://foggry.com/blog/2014/08/08/ping-mu-xuan-zhuan-xue-xi-bi-ji/

iOS屏幕旋转 浅析相关推荐

  1. iOS 屏幕旋转问题总结

    1.两个Orientation 1.1设备的物理方向(UIDeviceOrientation) typedef NS_ENUM(NSInteger, UIDeviceOrientation) {UID ...

  2. ios屏幕旋转学习笔记

    加速计是整个IOS屏幕旋转的基础,依赖加速计,设备才可以判断出当前的设备方向,IOS系统共定义了以下七种设备方向: typedef NS_ENUM(NSInteger, UIDeviceOrienta ...

  3. iOS屏幕旋转及其基本适配方法

    屏幕旋转示例.jpeg 前段时间抽空总结了一下iOS视频播放的基本用法,发现这其中还有一个我们无法绕过的问题,那就是播放界面的旋转与适配.的确,视频播放与游戏类型的App经常会遇到这个的问题.由于至今 ...

  4. iOS屏幕旋转那些事

    前些日子处理了一些关于页面中的屏幕旋转的事情,需要根据某个页面的不同旋转方向去做不同的处理,现在再次总结一下,以在心里有个系统的体系,也可以当成工具文章查询. 首先来看第一个方法: [UIDevice ...

  5. IOS 屏幕旋转Orientation总结

    IOS Orientation, 想怎么转就怎么转~~~ 此博文主要针对IOS应用, 是屏幕旋转相关问题的一个总结. 主要内容有: IOS5,6,7不同版的适配. 强制旋转和自动旋转. 博客: htt ...

  6. iOS屏幕旋转技术点及解决方案总结

    1.屏幕旋转相关枚举 关于屏幕旋转枚举一共有3种: UIInterfaceOrientation,    UIInterfaceOrientationMask,   UIDeviceOrientati ...

  7. IOS屏幕旋转的检测 与 强行切换

    mark – 屏幕的手动切换 [[UIDevice currentDevice]setValue:[NSNumber numberWithInteger:UIDeviceOrientationLand ...

  8. iOS 屏幕旋转常用方式

    //此方法在进入应用和当屏幕旋转的额时候,会调用 - (UIInterfaceOrientationMask)application:(UIApplication *)application supp ...

  9. iOS屏幕旋转,强制横竖屏

    在 iPhone 应用里,有时我们想强行把显示模式从纵屏改为横屏(反之亦然),特别是需要展示音频,视频播放器的时候需要进行横竖屏切换,下面做下横竖屏总结,如有不全面之处欢迎留言补充. 目前横竖屏旋转方 ...

最新文章

  1. Windows下sc create命令行添加/创建/修改服务
  2. TCP三次握手及其背后的缺陷
  3. 【转】datagridview的checkbox列,当修改checkbox状态时实时获得其准确状态值
  4. 【转】WebSocket详解(一):初步认识WebSocket技术
  5. react如何在父组件中调用子组件事件
  6. Git Submodule新漏洞已修复
  7. 抓取经过无线路由器的数据_无线网关是什么 无线网关的作用
  8. 【Spring】actual transaction available for current thread - cannot reliably process ‘remove‘ call
  9. webRTC之gtest安装使用(十五)
  10. excel去重怎么操作_EXCEL根据进货、出货求库存怎么操作
  11. h5常见的几种表现形式
  12. 机器学习环境配置(Tesla K80安装PyTorch的全过程)
  13. cc联盟网-中国最佳电子商务托管平台
  14. QQ农场之舌尖上的美食(20210729~20211021)
  15. 计算机锁屏打不开,电脑快捷锁屏不能用怎么办
  16. SQL-持仓天数分布
  17. 日本寿司第一人有多夸张?米饭用扇子降温,学徒十年才有资格煎蛋
  18. 阿里云 幸运券 分享 2017 10
  19. 小程序集成网易云通信群聊功能Demo发布
  20. 同花顺资金监测精鹰指标公式源码 通过资金监测强弱

热门文章

  1. 关于进程资源限制的getrlimit和setrlimit函数(epoll、服务器经常用)
  2. python 判断文件夹或文件是否存在
  3. [hihoCoder 1384]Genius ACM
  4. hadoop 集群启动时 Address already in use 解决方法
  5. 网络采集库NCrawler
  6. repeater的嵌套(转+总结)[http://www.cnblogs.com/esshs/archive/2005/04/07/132825.html]
  7. Google搜索正在“死亡”
  8. 人工智能时代,决定未来的3个问题
  9. 详解数据治理相关的7个术语和名词
  10. 产品经理最重要的3个能力