此博文主要针对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. python3  threading初体验

    python3中thread模块已被废弃,不能在使用thread模块,为了兼容性,python3将thread命名为_thread.python3中我们可以使用threading进行代替. threa ...

  2. Fis3的前端工程化之路[三大特性篇之声明依赖]

    Fis3版本:v3.4.22 Fis3的三大特性 资源定位:获取任何开发中所使用资源的线上路径 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中 依赖声明:在一个文本文 ...

  3. ASP.NET Aries 入门开发教程1:框架下载与运行

    背景: 鉴于框架的使用者越来越多,文档太少,不少用户反映框架的入门门槛太高. 好吧,再辛苦下,抽时间写教程吧! 步骤1:下载框架源码 开源地址:https://github.com/cyq1162/A ...

  4. 【初学python】使用python调用monkey测试

    目前公司主要开发安卓平台的APP,平时测试经常需要使用monkey测试,所以尝试了下用python调用monkey,代码如下: import os apk = {'j': 'com.***.test1 ...

  5. 【开源】.net 分布式架构之监控平台

    开源地址:http://git.oschina.net/chejiangyi/Dyd.BaseService.Monitor .net 简单监控平台,用于集群的性能监控,应用耗时监控管理,统一日志管理 ...

  6. 更愉快的书写CSS

    我在写CSS的时候经常会碰到些麻烦事儿: 1)看上去蛮简单的排版却写了很久 2)代码写的越来越散,总是这里补一句,那里补一句,没有条理性 3)margin.padding.font-size等属性在不 ...

  7. node中的Stream-Readable和Writeable解读

    在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream.Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream.Reader.Outpu ...

  8. ObserverPattern(观察者模式)

    import java.util.ArrayList; import java.util.List; /** * 观察者模式 * @author TMAC-J * 牵一发而动全身来形容观察者模式在合适 ...

  9. springmvc SSM shiro redis 后台框架 多数据源 代码生成器

    A集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单 下载地址    ; freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类 ...

  10. 在开源中国(oschina)git中新建标签(tags)

    我今天提交代码到主干上面,本来想打个标签(tags)的. 因为我以前新建过标签(tags),但是我现在新建的时候不知道入库在哪了.怎么找也找不到了. 从网上找资料也没有,找客服没有人理我,看到一个交流 ...