標籤:before ring device 通過 經理 支援 rom hang bar
此博文主要針對IOS應用, 是旋轉螢幕相關問題的一個總結. 主要內容有:
- IOS5,6,7不同版的適配.
- 強制旋轉和自動旋轉.
- QQ : 1101819159
- 郵箱: [email protected]
- 作者: Magic-Van.
- 時間: 2016-11-25
改變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支援的方向的子集.
UIViewControllerIOS6 and abovesupportedInterfaceOrientations
在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的方向. 則可以使用這樣:
-(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方法即可.
強制旋轉
有時候, 需要不隨系統旋轉, 而是強制旋轉到某一個角度. 最典型的情境就是視頻播放器, 當點擊了全屏按鈕的時候, 需要橫過來顯示.
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