玩轉IOS 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的方法來實現.
相關文章
相關標籤/搜索