iOS的橫屏(Landscape)與豎屏(Portrait)

蘋果開發中對iOS應用的橫屏(Landscape)和豎屏(Portrait)的支持情況。

0. 應用級別的配置

大家(特指有iOS開發經驗的人)應該都知道Xcode Project的工程配置General頁籤中有那麼四個圖(或者4個checkbox),標識對四種interfaceOrientation的支持。分別爲Portrait、PortraitUpsideDown、LandscapeLeft和LandscapeRight。

對應的,在Xcode Project工程配置的Info頁,實際上就是Info.plist中,有對4種Orientation的記錄項。

這兩者是一樣的。

1. Window級別的控制

在iOS6.0之後,UIApplicationDelegate中多了一個方法聲明:

1
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window

就是對於特定的application和特定的window,我們需要支持哪些interfaceOrientation,這是可以通過實現這個方法定製的。

返回值是一個無符號整數,實際上是可以使用定義好的枚舉值:

1
2
3
4
5
6
7
8
9
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),
};

對於UIApplicationDelegate的這個方法聲明,大多數情況下application就是當前的application,而window通常也只有一個。所以基本上通過window對橫屏豎屏interfaceOrientation的控制相當於全局的。

2. Controller層面的控制

老版本的iOS有這樣一個方法:

1
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation NS_DEPRECATED_IOS(2_0, 6_0);

即定製是否可以旋轉到特定的interfaceOrientation。

而在iOS6之後,推出了2個新的方法來完成這個任務:

1
2
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0);
- (NSUInteger)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0);

可以看得出來,兩個和在一起就是原來任務的完成過程。其中,大概的判斷方式是,先執行前者,判斷是否可以旋轉,如果爲YES,則根據是否支持特定的interfaceOrientation再做決斷。

3. 使得特定ViewController堅持特定的interfaceOrientation

iOS6之後還提供了這樣一個方法,可以讓你的Controller倔強第堅持某個特定的interfaceOrientation:

1
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0);

這就叫堅持,呵呵!
當然,使用這個方法是有前提的,就是當前ViewController是通過全屏的Presentation方式展現出來的。

這裏使用的是另外一套枚舉量,可以去UIApplication.h中查看定義。

4. 當前屏幕方向interfaceOrientation的獲取

有3種方式可以獲取到“當前interfaceOrientation”:

  • controller.interfaceOrientation,獲取特定controller的方向
  • [[UIApplication sharedApplication] statusBarOrientation] 獲取狀態條相關的方向
  • [[UIDevice currentDevice] orientation] 獲取當前設備的方向

具體區別,可參見StackOverflow的問答:

http://stackoverflow.com/questions/7968451/different-ways-of-getting-current-interface-orientation

5. 容器Controller的支持

上面把interfaceOrientation方向的獲取和支持配置都說了,看起來沒什麼問題了。有沒有什麼特殊情況?

當你使用TabbarController和NavigationController按照如上做法使用的時候就會有些頭疼。

辦法不是沒有,比較通俗的一種就是——繼承實現。

(補充:iOS7之後可以通過delegate對此進行控制)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章