IOS Orientation, 想怎么转就怎么转~~~
此博文主要针对IOS应用, 是屏幕旋转相关问题的一个总结. 主要内容有:
- IOS5,6,7不同版的适配.
- 强制旋转和自动旋转.
- 博客: http://www.cnblogs.com/jhzhu
- 邮箱: jhzhuustc@gmail.com
- 作者: 知明所以
- 时间: 2013-12-12
改变Orientation的三种途径
这里, 咱们主要理清一下: 到底有哪些设置可以改变屏幕旋转特性. 这样:
- 出现任何问题我们都可以从这几个途径中发现原因.
- 灵活应付产品经理的各种需求.
首先我们得知道:
- 当手机的重力感应打开的时候, 如果用户旋转手机, 系统会抛发
UIDeviceOrientationDidChangeNotification
事件. - 您可以分别设置
Application
和UIViewcontroller
支持的旋转方向.Application
的设置会影响整个App,UIViewcontroller
的设置仅仅会影响一个viewController
(IOS5和IOS6有所不同,下面会详细解释). - 当
UIKit
收到UIDeviceOrientationDidChangeNotification
事件的时候, 会根据Application
和UIViewcontroller
的设置, 如果双方都支持此方向, 则会自动屏幕旋转到这个方向. 更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
支持的方向. 但是, 只有两种情况下此方法才会生效:
- 当前
viewController
是window
的rootViewController
. - 当前
viewController
是modal
模式的. 即, 此viewController
是被调用presentModalViewController
而显示出来的.
在以上两种情况中,UIViewController.supportedInterfaceOrientations
方法会作用于当前viewController
和所有childViewController
. 以上两种情况之外, UIKit
并不会理会你的supportedInterfaceOrientations
方法.
举个栗子:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
}
如果某个viewController
实现了以上方法. 则, 此viewController
就支持竖方向和左旋转方向. 此viewController
的所有childViewController
也同时支持这两个方向, 不多不少.
preferredInterfaceOrientationForPresentation
此方法也属于UIViewController
. 影响当前viewController
的初始显示方向. 此方法也仅有在当前viewController
是rootViewController
或者是modal
模式时才生效.
shouldAutorotate
此方法,用于设置当前viewController
是否支持自动旋转. 如果,你需要viewController
暂停自动旋转一小会儿. 那么可以通过这个方法来实现.同样的, 此方法也仅有在当前viewController
是rootViewController
或者是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
最后一个方法是设置UIView
的transform
属性来强制旋转.
见下代码:
//设置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;
需要注意的是:
- 当然我们可以对当前
viewController
进行旋转, 对任何view
旋转都可以.但是, 你会发现navigationBar
还横在那里. 所以, 我们最好对一个占满全屏的view
进行旋转. 在这里我们旋转的对象是self.navigationController.view
, 当然self.window
也可以, help yourself~ - 我们需要显式的设置
bounds
.UIKit
并不知道你偷偷摸摸干了这些事情, 所以没法帮你自动设置.
如何应付产品经理的需求
有了以上三把武器, 我想基本可以应付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 Orientation, 想怎么转就怎么转~~~的更多相关文章
- iOS Orientation获取
[iOS Orientation获取] 1.[[UIDevice sharedInstance] orientation] 必须调用beginGeneratingDeviceOrientationNo ...
- iOS Orientation bug
Every September means pain for iOS developers- you need to make sure your old apps/code run on the n ...
- ios输出想保留的整数位(占位符)
int startHour=5; int startMinute=4; //输出前面补0,不管你输入的数据前面有没有0 sp;NSLog(@"====>%@",[NSStri ...
- iOS屏幕旋转 浅析
一.两种orientation 了解屏幕旋转首先需要区分两种orientation 1.device orientation 设备的物理方向,由类型UIDeviceOrientation表示,当前设备 ...
- View Programming Guide for iOS ---- iOS 视图编程指南(四)---Views
Views Because view objects are the main way your application interacts with the user, they have many ...
- 分分钟搞定IOS远程消息推送
一.引言 IOS中消息的推送有两种方式,分别是本地推送和远程推送,本地推送在http://my.oschina.net/u/2340880/blog/405491这篇博客中有详细的介绍,这里主要讨论远 ...
- iOS开发中获取WiFi相关信息
iOS 开发中难免会遇到很多与网络方面的判断,这里做个汇总,大多可能是与WiFi相关的. 1.Ping域名.Ping某IP 有 时候可能会遇到ping 某个域名或者ip通不通,再做下一步操作.这里的p ...
- iOS Wi-Fi
查漏补缺集是自己曾经做过相关的功能,但是重做相关功能或者重新看到相关功能的实现,感觉理解上更深刻.这一类的文章集中记录在查漏补缺集. iOS 开发中难免会遇到很多与网络方面的判断,这里做个汇总,大多可 ...
- 【零基础学习iOS开发】【转载】
原文地址:http://www.cnblogs.com/mjios/archive/2013/04/24/3039357.html 本文目录 一.什么是iOS 二.主流手机操作系统 三.什么是iOS开 ...
随机推荐
- kFreeBsd 国内开源镜像站汇总
从http://bbs.chinaunix.net/archiver/tid-3756178.html这里抽取了debian源中支撑kfreebsd架构的源. 中科大: http://debian.u ...
- Hibernate Validator
http://docs.jboss.org/hibernate/validator/4.2/reference/zh-CN/html_single/#example-group-interfaces
- JMS学习(四) Selector详解
一.前言 在掌握了消息的结构之后,我们接下来看一下JMS的一个重要功能:选择器.有些时候,作为消费者只希望处理自己感兴趣的消息.如果某个消息只有一个消费者,我们可以在让该客户端根据规则来处理自己感兴趣 ...
- lnmp+phpmyadmin配置与出现问题
本博客归moka同学(新浪微博:moka同学)本人亲自整理,如有使用,请加链接注明出处. lnmp 安装完全后,配置phpmyadmin .其访问方式为 http://202.18.400.379/p ...
- PHP学习笔记:用php读取xml文件
xml已经被json逐渐替代,现在用的api都是用貌似用的json,但是有些老的网站还是在用xml. 这里默认xml文件为:address.xml,存放在和读取的php文件相同级别目录,xml内容如下 ...
- ubuntu定时执行脚本(crond)
如果发现您的系统里没有这个命令,请安装下面两个软件包. vixie-cron crontabs crontab 是用来让使用者在固定时间或固定间隔执行程序之用,换句话说,也就是类似使用者的时程表.-u ...
- Objective-C学习笔记---构造函数和析构函数
简单的讲,构造函数就是在创建一个对象的时候起到初始化的作用,对这个对象里的一些成员变量进行初始化,析构函数就是在对象被删除进行一些清理工作,也就是专门的扫尾工作,下面用代码来进行具体说明. 一.构造函 ...
- [leetcode] Contains Duplicate
Contains Duplicate Given an array of integers, find if the array contains any duplicates. Your funct ...
- iOS实现(超级猜图)源码
//首先建立模型文件 QLLQuestion.hheQLLQuestion.m文件 #import <Foundation/Foundation.h> @interface QLLQues ...
- CoreAnimation-03-隐式动画
简介 每个UI控件,默认自动创建一个图层(根图层),即每个UI控件对应于至少一个图层 可以手动创建图层,这些图层为非根图层 对非根图层的某些属性(标记为Animatable的属性)进行修改,默认会自动 ...