標籤:
iOS 中橫豎屏切換的功能,在開發iOS app中總能遇到。以前看過幾次,感覺簡單,但是沒有敲過代碼實現,最近又碰到了,demo嘗試了幾種情況,這裡就做下總結。
注意
橫屏兩種情況是反的你知道嗎?
UIInterfaceOrientationLandscapeRight與UIInterfaceOrientationMaskLandscapeRight都代表橫屏,Home鍵在右側的情況;UIDeviceOrientationLandscapeLeft則是Home鍵在左側。
一般情形
所有介面都支援橫豎屏切換
如果App的所有切面都要支援橫豎屏的切換,那隻需要勾選【General】 中的【Device Orientation】,選擇希望支援的方向即可。
圖中支援豎屏和Home在右側
如上設定完之後,當裝置豎屏的時候,所有的介面都是豎屏顯示的;而當裝置橫屏Home在右側時,所有的介面會橫屏顯示。其他方向不支援,介面不會改變。
這裡有個坑:
在iOS 9 之後橫屏時,狀態列會消失。
解決方案:確保plist 中的【View controller-based status bar appearance】為YES,然後重寫ViewController的 - (BOOL)prefersStatusBarHidden ,傳回值是NO。
- (BOOL)prefersStatusBarHidden{ return NO;}
特殊情形
個別介面固定方向,其他所有介面都支援橫豎屏切換
這種情況,在【General】-->【Device Orientation】中設定好支援的方向後,只需要在這些特殊的視圖控制器中重寫兩個方法:
// 支援裝置自動旋轉- (BOOL)shouldAutorotate{ return YES;}/** * 設定特殊的介面支援的方向,這裡特殊介面只支援Home在右側的情況*/- (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscapeRight;}
個別介面支援橫豎屏切換,其他所有介面都固定方向
可能大多數App會是這種需求,某些特殊介面只能橫屏,如視頻播放類App。
這裡有兩種處理方式:
方式一
在【General】-->【Device Orientation】中設定好需要支援的所有方向。然後使用一個基類控制器,在基類控制器中重寫兩個控制橫豎屏的方法:
// 支援裝置自動旋轉- (BOOL)shouldAutorotate{ return YES;}// 支援豎屏顯示- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskPortrait;}
再然後,特殊的介面上再重寫這倆方法,讓其可以自動切換方向。
// 如果需要橫屏的時候,一定要重寫這個方法並返回NO- (BOOL)prefersStatusBarHidden{ return NO;}// 支援裝置自動旋轉- (BOOL)shouldAutorotate{ return YES;}// 支援橫屏顯示- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ // 如果該介面需要支援橫豎屏切換 return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortrait; // 如果該介面僅支援橫屏 // return UIInterfaceOrientationMaskLandscapeRight;}
方式二
用方式一的方法,還需要藉助一個基類,所有的控制器都要繼承這個基類,太麻煩?
另一種方式,是藉助通知來控制介面的橫豎屏切換。
還是整個App中大部分介面都是豎屏,某個介面可以橫豎屏切換的情況。
首先,在【General】-->【Device Orientation】設定僅支援豎屏,like this:
Device Orientation
然後在特殊的視圖控制器裡的ViewDidLoad中註冊通知:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil];
通知方法的實現過程:
- (void)deviceOrientationDidChange{ NSLog(@"deviceOrientationDidChange:%ld",(long)[UIDevice currentDevice].orientation); if([UIDevice currentDevice].orientation == UIDeviceOrientationPortrait) { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]; [self orientationChange:NO]; //注意: UIDeviceOrientationLandscapeLeft 與 UIInterfaceOrientationLandscapeRight } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft) { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; [self orientationChange:YES]; }}- (void)orientationChange:(BOOL)landscapeRight{ if (landscapeRight) { [UIView animateWithDuration:0.2f animations:^{ self.view.transform = CGAffineTransformMakeRotation(M_PI_2); self.view.bounds = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); }]; } else { [UIView animateWithDuration:0.2f animations:^{ self.view.transform = CGAffineTransformMakeRotation(0); self.view.bounds = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); }]; }}// 用到的兩個宏: #define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width) #define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
最重要的一點:
需要重寫如下方法,並且返回NO。
- (BOOL)shouldAutorotate{ return NO;}
這樣,在裝置出於橫屏時,介面就會變成橫屏,裝置處於豎屏時,介面就會變成豎屏。
填坑
// UINavigationController:- (BOOL)shouldAutorotate{ return [self.topViewController shouldAutorotate];}- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ return [self.topViewController supportedInterfaceOrientations];}// UITabBarController:- (BOOL)shouldAutorotate{ return [self.selectedViewController shouldAutorotate];}- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ return [self.selectedViewController supportedInterfaceOrientations];}
// 橫屏- (IBAction)landscapAction:(id)sender { [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight]; [self orientationChange:YES];}
但是按照上面的寫法,會導致返回到之前的介面時,視圖方向錯誤,即使返回前執行如下代碼:
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];[self orientationChange:NO];
也沒有作用,下面是在開源工程中無意看到的寫法:
// 橫屏- (IBAction)landscapAction:(id)sender { [self interfaceOrientation:UIInterfaceOrientationLandscapeRight];}// 豎屏- (IBAction)portraitAction:(id)sender { [self interfaceOrientation:UIInterfaceOrientationPortrait];}- (void)interfaceOrientation:(UIInterfaceOrientation)orientation{ 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 = orientation; [invocation setArgument:&val atIndex:2]; [invocation invoke]; }}
上面的方法會將裝置的方向強制設定為某個方向,然後再監控裝置方向改變的通知,即可實現橫豎屏切換。
這裡有一個用JS 和原生item 控制橫豎屏切換的Demo。地址
這是:
橫豎屏切換.gif
橫豎屏切換總結就到這來了,Have Fun!
摘自:http://www.cocoachina.com/ios/20160722/17148.html 感謝作者的分享,收藏備用
iOS 橫豎屏切換(應對特殊需求)