此博文主要针对IOS应用, 是屏幕旋转相关问题的一个总结. 主要内容有:

  1. IOS5,6,7不同版的适配.
  2. 强制旋转和自动旋转.

  • QQ : 1101819159
  • 邮箱: GeekiVan@aliyun.com
  • 作者: Magic-Van.
  • 时间: 2016-11-25

改变Orientation的三种途径

这里, 咱们主要理清一下: 到底有哪些设置可以改变屏幕旋转特性. 这样:

  • 出现任何问题我们都可以从这几个途径中发现原因.
  • 灵活应付产品经理的各种需求.

首先我们得知道:

  1. 当手机的重力感应打开的时候, 如果用户旋转手机, 系统会抛发UIDeviceOrientationDidChangeNotification 事件.
  2. 您可以分别设置ApplicationUIViewcontroller支持的旋转方向.Application的设置会影响整个App, UIViewcontroller的设置仅仅会影响一个viewController(IOS5和IOS6有所不同,下面会详细解释).
  3. UIKit收到UIDeviceOrientationDidChangeNotification事件的时候, 会根据ApplicationUIViewcontroller的设置, 如果双方都支持此方向, 则会自动屏幕旋转到这个方向. 更code的表达就是, 会对两个设置求,得到可以支持的方向. 如果求之后,没有任何可支持的方向, 则会抛发UIApplicationInvalidInterfaceOrientationException异常.

Info.plist设置

在App的Info.plist里设置:

key xcode name Summary avilable value
UIInterfaceOrientation initial interface orientation Specifies the initial orientation of the app’s user interface. UIInterfaceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft,
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations Supported interface orientations Specifies the orientations that the app supports. UIInterfaceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft,
UIInterfaceOrientationLandscapeRight

在Info.plist中设置之后,这个app里所有的viewController支持的自动旋转方向都只能是app支持的方向的子集.

UIViewController

IOS6 and above

supportedInterfaceOrientations

在IOS6及以上的版本中, 增添了方法UIViewController.supportedInterfaceOrientations. 此方法返回当前viewController支持的方向. 但是, 只有两种情况下此方法才会生效:

  1. 当前viewControllerwindowrootViewController.
  2. 当前viewControllermodal模式的. 即, 此viewController是被调用presentModalViewController而显示出来的.

在以上两种情况中,UIViewController.supportedInterfaceOrientations方法会作用于当前viewController和所有childViewController. 以上两种情况之外, UIKit并不会理会你的supportedInterfaceOrientations方法.

举个栗子:

- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
}

如果某个viewController实现了以上方法. 则, 此viewController就支持竖方向和左旋转方向. 此viewController的所有childViewController也同时支持这两个方向, 不多不少.

preferredInterfaceOrientationForPresentation

此方法也属于UIViewController. 影响当前viewController的初始显示方向. 此方法也仅有在当前viewControllerrootViewController或者是modal模式时才生效.

shouldAutorotate

此方法,用于设置当前viewController是否支持自动旋转. 如果,你需要viewController暂停自动旋转一小会儿. 那么可以通过这个方法来实现.同样的, 此方法也仅有在当前viewControllerrootViewController或者是modal模式时才生效.

IOS5 and before

在IOS5和以前的版本中, 每个viewController都可以指定自己可自动旋转的方向.(这样不是挺好么?苹果那帮工程师为啥要搞成这样...).
每当UIkit收到UIDeviceOrientationDidChangeNotification消息的时候, 就会用以下方法询问当前显示的viewController支不支持此方向:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
if ((orientation == UIInterfaceOrientationPortrait) ||
(orientation == UIInterfaceOrientationLandscapeLeft))
return YES; return NO;
}

特别要注意的是:你必须至少要对一个方向返回YES.(为难系统总不会有啥好事儿,你懂得).

UIView.transform

最后一个方法是设置UIViewtransform属性来强制旋转. 
见下代码:

//设置statusBar
[[UIApplication sharedApplication] setStatusBarOrientation:orientation]; //计算旋转角度
float arch;
if (orientation == UIInterfaceOrientationLandscapeLeft)
arch = -M_PI_2;
else if (orientation == UIInterfaceOrientationLandscapeRight)
arch = M_PI_2;
else
arch = 0; //对navigationController.view 进行强制旋转
self.navigationController.view.transform = CGAffineTransformMakeRotation(arch);
self.navigationController.view.bounds = UIInterfaceOrientationIsLandscape(orientation) ? CGRectMake(0, 0, SCREEN_HEIGHT, SCREEN_WIDTH) : initialBounds;

需要注意的是:

  1. 当然我们可以对当前viewController进行旋转, 对任何view旋转都可以.但是, 你会发现navigationBar还横在那里. 所以, 我们最好对一个占满全屏的view进行旋转. 在这里我们旋转的对象是self.navigationController.view, 当然self.window也可以, help yourself~
  2. 我们需要显式的设置boundsUIKit并不知道你偷偷摸摸干了这些事情, 所以没法帮你自动设置.

如何应付产品经理的需求

有了以上三把武器, 我想基本可以应付BT产品经理所有的需求了. 但是这里还有一些小技巧.

直接锁死

(略)

随系统旋转

IOS5及之前

对于IOS5及之前的版本, 只要在对每个viewController重写shouldAutorotateToInterfaceOrientation方法, 即可方便的控制每个viewController的方向.

IOS6及以后

对于IOS6及以后的版本, 如果想方便的单独控制每个viewController的方向. 则可以使用这样:

  • 对于非modal模式的viewController:

    • 如果不是rootViewController,则重写supportedInterfaceOrientations,preferredInterfaceOrientationForPresentation以及shouldAutorotate方法, 按照当前viewController的需要返回响应的值.
    • 如果是rootViewController,则如下重写方法:
-(NSUInteger)supportedInterfaceOrientations
{
return self.topMostViewController.supportedInterfaceOrientations;
}
-(BOOL)shouldAutorotate
{
return [self.topMostViewController shouldAutorotate];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topMostViewController preferredInterfaceOrientationForPresentation];
}
-(UIViewController*)topMostViewController
{
//找到当前正在显示的viewController并返回.
}

显而易见, 我们巧妙的绕开了UIKit只调用rootViewController的方法的规则. 把决定权交给了当前正在显示的viewController.

  • 对于modal模式的viewController. 则按照需要重写supportedInterfaceOrientations,preferredInterfaceOrientationForPresentation以及shouldAutorotate方法即可.

强制旋转

有时候, 需要不随系统旋转, 而是强制旋转到某一个角度. 最典型的场景就是视频播放器, 当点击了全屏按钮的时候, 需要横过来显示.

  • 对于IOS5及以前的版本, 可以用下面的方法:
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 = UIInterfaceOrientationLandscapeRight;
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
  • 对于IOS6及以后的版本. UIDevice.setOrientation从隐藏变为移除.只能通过设置UIView.transform的方法来实现.

iOS----应用的旋转---Orientations的更多相关文章

  1. iOS实现屏幕旋转

    iOS实现屏幕旋转有两种方式 1. 应用本身支持 2. 手动旋转UIView (这种方式我没找到旋转 系统控件的方法 如:键盘.导航.UIAlertView) 如果你只是要把竖屏的播放器,做成支持横屏 ...

  2. iOS 图片裁剪 + 旋转

    iOS 图片裁剪 + 旋转 之前分别介绍了图片裁剪和图片旋转方法 <iOS 图片裁剪方法> 地址:http://www.cnblogs.com/silence-cnblogs/p/6490 ...

  3. ios实现屏幕旋转的方法

    1.屏蔽AppDelegate下面的屏幕旋转方法 #pragma mark - 屏幕旋转的 //- (UIInterfaceOrientationMask)application:(UIApplica ...

  4. 【iOS】屏幕旋转,屏幕自适应方向变化

    1. iOS有四个方向的旋转,为了保证自己的代码能够支持旋转,我们必须首先处理一个函数: - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInter ...

  5. 监听iOS检测屏幕旋转状态,不需开启屏幕旋转-b

    -(void)rotation_icon:(float)n { UIButton *history_btn= [self.view viewWithTag:<#(NSInteger)#>] ...

  6. (转)ios限制控制器旋转

    iOS屏幕旋转控制 iOS屏幕旋转控制(iOS6之后)       iOS6之前,子控制器只要覆盖父类的shouldAutorotateToInterfaceOrientation:方法就能单独控制某 ...

  7. js 前端图片压缩+ios图片角度旋转

    step1:读取选择的图片,并转为base64: function ImgToBase64 (e, fn) { // 图片方向角 //fn为传入的方法函数,在图片操作完成之后执行 var Orient ...

  8. iOS拍照图片旋转的问题

    很久之前,遇到了这种情况,iOS某端拍照上传到服务器,其他iOS端从服务器下载该照片展示,发现图片逆时针旋转了90度.当时百度了一下,找到一段代码修正image方向,问题解决了,但没有深入理解底层原理 ...

  9. ios 关于屏幕旋转和屏幕晃动

    内置加速计是智能手机最酷的特性之一,ios可以通过这个小设备知道用户握持手机的方式,以及用户是否移动了手机,ios使用加速计处理自动旋转,并且许多游戏都是用它作为控制机制,它还可以用于检测摇动和其他突 ...

随机推荐

  1. shell注释

    sh里没有多行注释,只能每一行加一个#号.只能像这样: #-------------------------------------------- # 这是一个自动打ipa的脚本,基于webfrogs ...

  2. HTTP常用状态码分析

    不管是面试还是工作中,经常会碰到需要通过HTTP状态码去判断问题的情况,比如对于后台RD,给到前端FE的一个接口,出现502或者504 error错误,FE就会说接口存在问题,如果没有知识储备,那就只 ...

  3. jQuery动画-圣诞节礼物

    ▓▓▓▓▓▓ 大致介绍 下午看到了一个送圣诞礼物的小动画,正好要快到圣诞节了,就动手模仿并改进了一些小问题 原地址:花式轮播----圣诞礼物传送 思路:动画中一共有五个礼物,他们平均分布在屏幕中,设置 ...

  4. 【开源】.Net Api开放接口文档网站

    开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务  238543768 ApiView .net api的接口文档查看 ...

  5. UWP开发之Mvvmlight实践八:为什么事件注销处理要写在OnNavigatingFrom中

    前一段开发UWP应用的时候因为系统返回按钮事件(SystemNavigationManager.GetForCurrentView().BackRequested)浪费了不少时间.现象就是在手机版的详 ...

  6. Python爬虫小白入门(四)PhatomJS+Selenium第一篇

    一.前言 在上一篇博文中,我们的爬虫面临着一个问题,在爬取Unsplash网站的时候,由于网站是下拉刷新,并没有分页.所以不能够通过页码获取页面的url来分别发送网络请求.我也尝试了其他方式,比如下拉 ...

  7. wordpress优化之结合prism.js为编辑器自定义按钮转化代码

    原文链接 http://ymblog.net/2016/07/24/wordpress-prism/ 继昨天花了一天一夜的时间匆匆写了主题Jiameil3.0之后,心中一直在想着优化加速,体验更好,插 ...

  8. C# 泛型

    C# 泛型 1.定义泛型类 在类定义中包含尖括号语法,即可创建泛型类: class MyGenericClass<T> { //Add code } 其中T可以遵循C#命名规则的任意字符. ...

  9. spring无法读取properties文件数据

    只讲述异常点,关于怎么配置文件,这里不做说明.   1. controller中无法读取config.properties文件 controller中注入的@Value配置是从servlet-cont ...

  10. 一个简单的网站web项目的详解

    有不对的术语,或者不好理解的部分,欢迎大家批评指正,谢谢大家! 近期做的网站web项目,实现登录功能,查询功能.首先把这个项目分为几个模块来处理,当前用户模块,历史用户模块,历史记录模块,数据库模块, ...