標籤:ios 旋轉螢幕 自動旋轉 手動旋轉 強制旋轉
1、布局適配方式本文不討論哪種布局適配方式最好,此處使用的是 Masonry 純程式碼布局適配。(Masonry 底層就是 AutoLayout 的 NSLayoutConstraint)
2、iOS 方向枚舉類
// 三維裝置方向typedef NS_ENUM(NSInteger, UIDeviceOrientation) { UIDeviceOrientationUnknown, UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left UIDeviceOrientationFaceUp, // Device oriented flat, face up UIDeviceOrientationFaceDown // Device oriented flat, face down};// 二維介面方向typedef NS_ENUM(NSInteger, UIInterfaceOrientation) { UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown, UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait, UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight, UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft};// iOS6 以後引入組合方式typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) { UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait), UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft), UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight), UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown), UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown), UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),};擷取裝置方向:[[UIDevice currentDevice] orientation]
擷取介面方向:[[UIApplication sharedApplication] statusBarOrientation]
3、iOS6 及其以上版本頁面旋轉設定方法
// 返回是否支援旋轉螢幕- (BOOL)shouldAutorotate{ return YES; }// 返回支援的旋轉方向- (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskAll; }// 返回優先顯示的螢幕方向,如果不設定,預設與進入前一個頁面保持一致(注意該方法只對 ModalViewController 有效)- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{ return UIInterfaceOrientationLandscapeLeft; }4、影響介面旋轉特性的層級因素(1)針對全域
Info.plist 檔案中 Supported interface orientations 支援的方向。
(2)針對 Window
AppDelegate 中 supportedInterfaceOrientationsForWindow 支援的方向。
(3)針對單個頁面
如果是 ChildrenViewController,則受限於其 RootViewController 中 shouldAutorotate 和 supportedInterfaceOrientations 支援的方向。(RootViewController 指 self.window.rootViewController 設定的那個 ViewController)
如果是 ModalViewController,則受限於其自身 shouldAutorotate 和 supportedInterfaceOrientations 支援的方向。(如果 ModalViewController 是經過封裝的另一個 RootViewController,則與上述 ChildrenViewController 原理類似)
注意:上述三個層級因素最終的交集即為子視圖控制器支援的旋轉方向,如果交集為空白,則會拋 UIApplicationInvalidInterfaceOrientationException 異常。
5、旋轉螢幕機制流程(1)加速計檢測到方向變化,發出 UIDeviceOrientationDidChangeNotification 通知。
(2)程式接收到通知,通過 AppDelegate 知會當前程式的 Window。
(3)Window 通知 RootViewController,根據以下設定決定是否旋轉。
- Info.plist 中 Supported interface orientations 是否支援該方向
- AppDelegate 中 supportedInterfaceOrientationsForWindow 中是否支援該方向
- RootViewController 中 shouldAutorotate 是否為 YES
- RootViewController 中 supportedInterfaceOrientations 是否支援該方向
(4)RootViewController 通知其 ChildrenViewController,同步旋轉操作。
一般情況下 ChildrenViewController 不單獨設定,與 RootViewController 保持一致。如果特殊情境需要單獨設定,可以通過在 RootViewController 中下放許可權,如:NavigationController 可以通過 self.topViewController 下放許可權;TabBarController 可以通過 self.selectedViewController 下放許可權。但是要注意,即使下放了許可權,ChildrenViewController 還是必須遵守 Info.plist 和 AppDelegate 中的設定。
(5)如果存在彈出的 ModalViewController,則不受限於步驟4中的 RootViewController,只根據 Info.plist、AppDelegate 及其自身所支援的旋轉設定決定是否旋轉。如果 ModalViewController 是經過封裝的另一個 RootViewController,則與步驟4原理類似。
6、產品開發中的應對策略。(1)應用只需要支援單一方向。在 Info.plist 中鎖死指定方向,限制旋轉螢幕。
(2)應用統一支援多個方向自動旋轉。在 Info.plist 中設定應用支援的方向,每個頁面進行相應的自動旋轉布局適配。
(3)應用不同頁面支援的方向不一致。在 Info.plist 中設定所有頁面支援的方向的並集,在 RootViewController 中將許可權下放,由頁面但與控制自己的旋轉設定。
7、實際情境應用(有樣本 Demo)注意:本文不考慮 iOS6 以下版本的相容性,所以下述 demo 只適配 iOS6 及其以上版本(只在 iOS7、iOS8 測試過)。下述情境處理方案中,iPad 預設支援四個方向,iPhone 預設支援 UIInterfaceOrientationMaskPortraitUpsideDown 三個方向。
(1)應用情境1:應用支援單一方向,限制旋轉。(iPhone 中一般此方式用得比較多)
思路:在 Info.plist 中鎖死指定方向,其他旋轉設定均不用配置,適配方式比較多,也比較容易,不過建議純程式碼的話還是通過 Masonry 進行布局適配。
樣本:LimitPortraitDemo
(2)應用情境2:應用統一支援多方向自動旋轉。(iPad 中一般此方式用得比較多)
思路:在 Info.plist 中設定應用支援的旋轉方向即可,其他旋轉設定均不用配置,布局要分別適配橫屏與豎屏,純程式碼的話建議通過 Masonry 進行布局適配。
樣本:AnyRotationDemo
(3)應用情境3:應用支援單一方向,但是個別頁面支援自動旋轉。(一般不建議使用,除非特定情境,如視頻播放器頁面,自動旋轉後橫屏觀看效果更好)
思路:在 Info.plist 中設定應用支援的所有旋轉方向,在 RootViewController 中通過 shouldAutorotate 和 supportedInterfaceOrientations 鎖死指定方向,然後在 ModalViewController 中通過 shouldAutorotate 和 supportedInterfaceOrientations 設定多個旋轉方向,並進行相應的布局適配。適配方式純程式碼的話同樣建議 Masonry。
樣本:SingleRotationDemo
(4)應用情境4:應用支援單一方向,但是個別頁面支援手動控制旋轉,不支援自動旋轉。(一般不建議使用,除非特定情境,如視頻播放器頁面限制自動旋轉,點擊全屏按鈕後橫屏觀看)
思路:有兩種強制方式旋轉方式,一種是帶導覽列的,一種是不帶導覽列的。具體實現思路樣本中有詳細描述。
樣本:ForceRotationDemo
8、相關注意事項
- 一般都不建議在程式裡面直接調用 UIDeviceOrientation 的方向,而是用 UIInterfaceOrientation。
- 擷取螢幕方法,不要使用[[UIDevice curentDevice] orientation],建議使用[[UIApplication sharedApplication] statusBarOrientation]。
- 如果 shouldAutorotate 返回 YES 的話,設定 setStatusBarOrientation 是不管用的。
- 如果 shouldAutorotate 返回 NO 的話,[[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)] 方法是不管用的。
- 盡量不要使用強制旋轉的方式,通過 present 出 ModalViewController 方式,單獨控制每個試圖控制器的旋轉設定。蘋果官方也是支援這種方式。
著作權聲明:本文為博主原創文章,轉載請聲明出處:http://blog.csdn.net/jinnchang
iOS6 及其以上版本自動旋轉、手動強制旋轉方案及布局適配