IOS5,6,7不一樣版的適配. 強制旋轉和自動旋轉.

改變Orientation的三種途徑xcode

這裏, 我們主要理清一下: 到底有哪些設置能夠改變屏幕旋轉特性. 這樣:app

  • 出現任何問題咱們均可以從這幾個途徑中發現緣由.ide

  • 靈活應付產品經理的各類需求.spa

首先咱們得知道:code

  1. 當手機的重力感應打開的時候, 若是用戶旋轉手機, 系統會拋發UIDeviceOrientationDidChangeNotification 事件.orm

  2. 您能夠分別設置Application和UIViewcontroller支持的旋轉方向.Application的設置會影響整個App, UIViewcontroller的設置僅僅會影響一個viewController(IOS5和IOS6有所不一樣,下面會詳細解釋).視頻

  3. 當UIKit收到UIDeviceOrientationDidChangeNotification事件的時候, 會根據Application和UIViewcontroller的設置, 若是雙方都支持此方向, 則會自動屏幕旋轉到這個方向. 更code的表達就是, 會對兩個設置求,獲得能夠支持的方向. 若是求以後,沒有任何可支持的方向, 則會拋發UIApplicationInvalidInterfaceOrientationException異常.對象

Info.plist設置事件

在App的Info.plist裏設置:ip

key   xcode nameSummaryavilable valueUIInterfaceOrientationinitial interface orientationSpecifies the initial orientation of the app’s user interface.UIInterfaceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft,
UIInterfaceOrientationLandscapeRightUISupportedInterfaceOrientationsSupported interface orientationsSpecifies the orientations that the app supports.UIInterfaceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft,
UIInterfaceOrientationLandscapeRight

在Info.plist中設置以後,這個app裏全部的viewController支持的自動旋轉方向都只能是app支持的方向的子集.



UIViewControllerIOS6 and abovesupportedInterfaceOrientations

在IOS6及以上的版本中, 增添了方法UIViewController.supportedInterfaceOrientations. 此方法返回當前viewController支持的方向. 可是, 只有兩種狀況下此方法纔會生效:

  1. 當前viewController是window的rootViewController.

  2. 當前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;

須要注意的是:

  1. 固然咱們能夠對當前viewController進行旋轉, 對任何view旋轉均可以.可是, 你會發現navigationBar還橫在那裏. 因此, 咱們最好對一個佔滿全屏的view進行旋轉. 在這裏咱們旋轉的對象是self.navigationController.view, 固然self.window也能夠, help yourself~

  2. 咱們須要顯式的設置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兩個強制旋轉屏幕的方法

  • Supporting Multiple Interface Orientations

相關文章
相關標籤/搜索