国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

iOS 屏幕旋轉問題總結

2019-11-08 00:18:33
字體:
來源:轉載
供稿:網友

1、兩個Orientation

1.1設備的物理方向(UIDeviceOrientation)

 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}

1.2界面的顯示方向(UIInterfaceOrientation)

typedef NS_ENUM(NSInteger, UIInterfaceOrientation) { UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown, UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait, UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight, UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft}

注意:

UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft

兩者是相反的,經過測試發現: 在【General】 -->【Deployment Info】-->【Device Orientation】勾選Landscape Right 設備支持的方向是聽筒在左,Home鍵在右的方向,而 此時打印的device方向是UIDeviceOrientationLandscapeLeft 打印的Interface的方向是UIInterfaceOrientationLandscapeLeft

這個是ios6之后新增的一組枚舉值,使用組合時更加方便,具體兩者有什么區別,暫時還沒搞清楚,使用時根據返回值類型選擇正確的格式,避免可能出現的bug

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),}

1.3獲取Orientation

設備 [UIDevice currentDevice].orientation @PRoperty(nonatomic,readonly) UIDeviceOrientation orientation; // return current device orientation. this will return UIDeviceOrientationUnknown unless device orientation notifications are being generated.

如果關閉了系統的橫豎屏切換開關,即系統層級只允許豎屏時,再通過上述方式獲取到的設備方向將是UIDeviceOrientationPortrait。 - 界面 self.interfaceOrientation ios之后8廢除 [UIapplication sharedApplication].statusBarOrientation

2、默認方向

2.1 Device

打開【General】 -->【Deployment Info】-->【Device Orientation】 可以發現Xcode默認支持的設備方向有PortraitLandscape LeftLandscape Right,Upside Down 方向是不支持的。 默認支持方向.png

此處我們把Upside Down勾中,發現在ipad中已經默認支持四個方向,但在iPhone中UpsideDown方向不會發生變化。

原因: **此處是設置支持的設備方向,界面看到的方向是Interface的方向,此時在全部選中的情況下(UIInterfaceOrientationMask)supportedInterfaceOrientations方法, iPad默認返回UIInterfaceorientationMaskAll, iPhone默認返回UIInterfaceOrientationMaskAllButUpsideDown。 iPhone若要支持UpsideDown,需重寫(UIInterfaceOrientationMask)supportedInterfaceOrientations**

具體設置方法,下面再詳細介紹。

2.2 Interface

打開【Info】 -->【Custom iOS Target Properties】-->【Supported interface orientations】 默認和【General】 -->【Deployment Info】-->【Device Orientation】值一樣

Interface默認支持方向.png

3、全局設置

Device的方向是我們是通過改變握持方向去改變的,不是代碼能夠改變的,所以這里對Device Orientation只有Support的概念。通過【General】 -->【Deployment Info】-->【Device Orientation】設置。

設置Interface Orientation有三種途徑

3.1 Info.plist設置

設置Interface方向.png 如圖所示,可以通過修改Info.plist里的UISupportedInterfaceOrientations的屬性修改InterfaceSupportOrientation

初始化界面方向.png

設置Interface的界面的Orientationplist里并沒有直接給出,需要我們自行添加,添加方式和UISupportedInterfaceOrientations相同。

注意: 【General】 -->【Deployment Info】-->【Device Orientation】設置設備支持方向時,plist里的Supported interface orientations會根據設備方向自動添加Interface的支持方向。如不需要某方向的UISupportedInterfaceOrientations,可以在Info.plist里手動修改,該修改并不會影響DeviceSupportOrientation

3.2 UIWindow設置

iOS6的UIApplicationDelegate提供了下述方法,能夠指定UIWindow中的界面的屏幕方向:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window NS_AVAILABLE_IOS(6_0);

該方法默認值為Info.plist中配置的Supported interface orientations項的值。

3.3 UIViewcontroller設置

三個方法

//Interface的方向是否會跟隨設備方向自動旋轉,如果返回NO,后兩個方法不會再調用- (BOOL)shouldAutorotate { return YES;}//返回直接支持的方向- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskPortrait;}//返回最優先顯示的屏幕方向- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait;}

解釋 1.第二個方法,在iPad上的默認返回值是UIInterfaceOrientationMaskAll,iPhone上的默認返回值是UIInterfaceOrientationMaskAllButUpsideDown 2.在前面DeviceOrientation即使全部勾選了,若要iPhone支持UpsideDown,也要在viewcontroller里重寫第二個方法。返回包含UpsideDown的方向; 3.第三個方法,比如同時支持PortraitLandscape方向,但想優先顯示Landscape方向,那軟件啟動的時候就會先顯示Landscape,在手機切換旋轉方向的時候仍然可以在PortraitLandscape之間切換;

這三個方法是iOS6之后才有的,有個特點是只在兩種情況下才生效

1.當前viewControllerwindowrootViewController 2.當前viewControllermodal模式的,即此viewController是調用presentModalViewController而顯示出來的.

在以上兩種情況中,supportedInterfaceOrientations的方法會作用于當前的viewController和所有的childViewController,如果不是以上的兩種情況下的viewControllerUIKit不會執行上述方法。

**這三種方法控制規則的交集就是一個viewController的最終支持的方向; 如果最終的交集為空,在iOS6以后會拋出UIApplicationInvalidInterfaceOrientationException崩潰異常。**

4、自定義設置

在實際的項目需求過程中,往往是有一些需要固定方向,有些需要支持旋轉適應的。剛才上面提到過,通過UIViewController的三個方法設置Orientation時,只有在是windowrootViewController或者modal模式下才生效。單獨設置某個viewController并沒有效果。這樣就給我們帶來了一些麻煩,通過調查研究,大概有這么幾種解決方案。

4.1 在rootViewController里加判斷

如:

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ if([[self topViewController] isKindOfClass:[subViewController class]]) return UIInterfaceOrientationMaskAllButUpsideDown; else return UIInterfaceOrientationMaskPortrait;}

或者在UINavigationControllerUITabBarController里重寫

-(UIInterfaceOrientationMask)supportedInterfaceOrientations{ return self.selectedViewController.supportedInterfaceOrientations;}-(BOOL)shouldAutorotate{ return [self.selectedViewController shouldAutorotate];}- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{ return [self.selectedViewController preferredInterfaceOrientationForPresentation];}

UINavigationController 使用self.topViewController UITabBarController 使用self.selectedViewController

然后在viewController重寫這三個方法,這樣就巧妙的繞開了UIKit只調用rootViewController的方法的規則. 把決定權交給了當前正在顯示的viewController.

但是 這樣是可以在當前viewController達到預期效果,但是在返回上一頁時,或者在當前頁面不不支持的方向的上一頁進來時,不能立即達到預期狀態,需要設備方向更換一次才能恢復正常。

解決方案:

#pragma mark -UITabBarControllerDelegate- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { [self presentViewController:[UIViewController new] animated:NO completion:^{ [self dismissViewControllerAnimated:NO completion:nil]; }];}#pragma mark -UINavigationControllerDelegate- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { [self presentViewController:[UIViewController new] animated:NO completion:^{ [self dismissViewControllerAnimated:NO completion:nil]; }];}

這樣就會觸發-(BOOL)shouldAutorotate方法和 -(UIInterfaceOrientationMask)supportedInterfaceOrientations方法,但是會閃一下,依然不完美。

4.2 把需要單獨設置的viewController添加在一個獨立的navgationController里

這種方法不適用rootViewControllerUITabBarController的, 不推薦使用。

4.3 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; statusBar不會自己旋轉,這里要首先設置statusBar的方向。ios9后setStatusBarOrientation方法廢除,在ios10中測試,不設置StatusBarOrientation會自動調整 我們這里選擇的是self.navigationController進行旋轉,當然也可以是self.view或者self.window,都可以,最好是全屏的view. 我們需要顯示的設置bounds,UIKit并不知道你偷偷摸摸干了這些事情。 -(BOOL)shouldAutorotate方法,應返回NO

在iOS 9 之后橫屏時,狀態欄會消失。

解決方法:確保Info.plist中的【View controller-based status bar appearance】YES,然后重寫viewController- (BOOL)prefersstatusBarHidden,返回值是NO。詳細參考iOS-UIStatusBar詳細總結

- (BOOL)prefersStatusBarHidden{ return NO;}

完美的方法待繼續研究!!!

5、強制旋轉

5.1 setOrientation的方法

setOrientation 在iOS3以后變為私有方法了,不能直接去調用此方法,否則后果就是被打回。 不能直接調用,但是可以間接的去調用,下面的方法就是利用 KVO機制去間接調用,多次驗證不會被打回,放心!

-(void)viewWillAppear:(BOOL)animated{//首先設置UIInterfaceOrientationUnknown欺騙系統,避免可能出現直接設置無效的情況 NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown]; [[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"]; NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];}

5.2 UIview.transform的方法

方法見4.3

參考文章: iOS屏幕旋轉學習筆記 [iOS]Orientation 想怎么轉就怎么轉 iOS 知識小集(橫豎屏切換) iOS強制改變物理設備方向的進階方法


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 南宁市| 盐山县| 铅山县| 达孜县| 永州市| 九寨沟县| 万山特区| 江安县| 上犹县| 平度市| 沧源| 灵石县| 鸡西市| 东至县| 新民市| 南安市| 长沙市| 墨脱县| 边坝县| 青龙| 天气| 育儿| 韶关市| 汤原县| 平乡县| 灵丘县| 隆安县| 巩留县| 浠水县| 伊宁市| 任丘市| 永和县| 芜湖县| 阜阳市| 上栗县| 娄烦县| 宜都市| 张家港市| 西青区| 太湖县| 新丰县|