在iOS6以前的版本中,一般使用 shouldAutorotateToInterfaceOrientation 來單獨控制某個UIViewController的方向,須要哪一個viewController支持旋轉,只須要重寫shouldAutorotateToInterfaceOrientation方法。html
可是iOS 6裏屏幕旋轉改變了不少,以前的 shouldAutorotateToInterfaceOrientation 被列爲 DEPRECATED 方法,查看UIViewController.h文件也能夠看到:ios
- // Applications should use supportedInterfaceOrientations and/or shouldAutorotate..
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation NS_DEPRECATED_IOS(2_0, 6_0);
程序將使用以下2個方法來代替:app
- - (BOOL)shouldAutorotate;
- - (NSUInteger)supportedInterfaceOrientations;
除了重寫這個2個方法,IOS6裏面要旋轉還有一些須要注意的地方,下面會細述。另外還有一個硬性條件,須要在Info.plist文件裏面添加程序支持的全部方向,能夠經過如下2種方式添加
1.ide
2.oop
另外要兼容IOS6以前的系統,要保留原來的 shouldAutorotateToInterfaceOrientation 方法,還有那些 willRotateToInterfaceOrientation 等方法。ui
IOS6自動旋轉設置:
IOS6裏面,控制某個viewController旋轉並非像IOS5或者IOS4同樣在這個viewController裏面重寫上面那2個方法,而是須要在這個viewController的rootViewController(根視圖控制器)裏面重寫,怎麼解釋呢?就是最前面的那個viewController,直接跟self.window接觸的那個controller,好比如下代碼:
- UIViewController *viewCtrl = [[UIViewController alloc] init];
- UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:viewCtrl];
- if ([window respondsToSelector:@selector(setRootViewController:)]) {
- self.window.rootViewController = navCtrl;
- } else {
- [self.window addSubview:navCtrl.view];
- }
若是須要設置viewCtrl的旋轉,那麼不能在UIViewController裏面重寫shouldAutorotate和supportedInterfaceOrientations方法,而是須要在navCtrl裏面設置,又由於UINavigationController是系統控件,因此這裏須要新建一個UINavigationController的子navigationController的子類,而後在裏面實現shouldAutorotate和supportedInterfaceOrientations方法,好比:
- -(NSUInteger)supportedInterfaceOrientations{
- return UIInterfaceOrientationMaskAllButUpsideDown;
- }
-
- - (BOOL)shouldAutorotate{
- return YES;
- }
eg1:若是上面的例子是self.window.rootViewController = viewCtrl,而不是navCtrl,那麼上面的那2個控制旋轉的方法就應該寫在UIViewController裏面!
eg2:若是viewCtrl又pushViewController到viewCtrl2,須要設置viewCtrl2的旋轉,怎麼辦呢? 仍是在navCtrl裏面控制,由於viewCtrl和viewCtrl2的rootViewController都是navCtrl,通常的寫法都是
- UIViewController *viewCtrl2 = [[UIVewController alloc] init];
- [self.navigationController.navigationController pushViewController:viewCtrl2 animated:YES];
因此要控制一個UINavigationController push到的全部viewController的旋轉,那麼就得在navCtrl裏面區分是哪一個viewController,以便對他們一一控制!一樣若是rootViewController是UITabbarController,那麼須要在子類化的UITabbarController裏面重寫那2個方法,而後分別控制!
可是有時候我初始化UINavigationController的時候,並不知道全部我全部須要push到的viewController,那麼這裏有一個通用的方法,就是讓viewController本身來控制本身,首先在navCtrl裏面的實現方法改成如下方式:
- - (BOOL)shouldAutorotate
- {
- return self.topViewController.shouldAutorotate;
- //topViewController爲UINavigationController的屬性
- }
-
- - (NSUInteger)supportedInterfaceOrientations
- {
- return self.topViewController.supportedInterfaceOrientations;
- }
所有調用self.topViewController,就是返回當前呈現出來的viewController裏面的設置,而後在viewCtrl、viewCtrl2等等這些viewController裏面重寫shouldAutorotate和supportedInterfaceOrientations,以方便設置每一個viewController的旋轉
eg3:若是viewCtrl 是 presentModalViewController 到 viewCtrl3,那麼viewCtrl3的旋轉設置就不在navCtrl裏面了!若是presentModalViewController的viewController是navController、tabbarController包裝過的viewCtrl3,那麼就應在新包裝的navController、tabbarController裏面設置,若是是直接presentModalViewController到viewCtrl3,那麼就在viewCtrl3裏面設置
這個簡單不少,沒有上面的硬性條件,只須要在須要旋轉的viewController裏面重寫 shouldAutorotateToInterfaceOrientation 方法就行
手動旋轉
手動旋轉也有2種方式,一種是直接設置 UIDevice 的 orientation,可是這種方式不推薦,上傳appStore有被拒的風險:spa
- if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
- [[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:(id)UIInterfaceOrientationPortrait];
- }
第二種是假旋轉,並無改變 UIDevice 的 orientation,而是改變某個view的 transform,利用 CGAffineTransformMakeRotation 來達到目的,好比:
- self.view.transform = CGAffineTransformMakeRotation(M_PI/2)
下面講解採用第二種方式的各版本手動旋轉:
思想是首先設置 statusBarOrientation,而後再改變某個view的方向跟 statusBarOrientation 一致!.net
IOS6手動旋轉:
1. 那既然是旋轉,最少也得有2個方向,那麼仍是少不了上面說的那個硬性條件,先在plist裏面設置好全部可能須要旋轉的方向。既然是手動旋轉,那麼就要關閉自動旋轉:code
- - (BOOL)shouldAutorotate{
- return NO;
- }
2.手動觸發某個按鈕,調用方法,這個方法的實現以下:
- [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
- self.view.transform = CGAffineTransformMakeRotation(M_PI/2);
- self.view.bounds = CGRectMake(0, 0, kScreenHeight, 320);
注意:
1. 只須要改變self.view.transform,那麼self.view的全部subview都會跟着自動變;其次由於方向變了,因此self.view的大小須要從新設置,不要使用self.view.frame,而是用bounds。
2. 若是shouldAutorotate 返回YES的話,下面設置setStatusBarOrientation 是無論用的!setStatusBarOrientation只有在shouldAutorotate 返回NO的狀況下才管用!
IOS五、IOS4手動旋轉:
1.在須要手動旋轉的viewController裏的 shouldAutorotateToInterfaceOrientation 方法設置 interfaceOrientation == [UIApplicationsharedApplication].statusBarOrientation
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
- return (interfaceOrientation == [UIApplication sharedApplication].statusBarOrientation);
- }
2.手動觸發某個按鈕,調用方法,這個方法的實現以下:
- [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
- self.view.transform = CGAffineTransformMakeRotation(M_PI/2);
- self.view.bounds = CGRectMake(0, 0, kScreenHeight, 320);
注意:只須要改變self.view.transform,那麼self.view的全部subview都會跟着自動變;其次由於方向變了,因此self.view的大小須要從新設置,不要使用self.view.frame,而是用bounds。
經驗分享:
1.IOS6裏面,若是一個項目裏面須要各類旋轉支持,有自動,有手動,那麼咱們能夠新建2個navController或者tabbarController的子類,一個是不旋轉,一個旋轉,那麼全部須要旋轉的UINavigationController均可以用這個子類來代替!包括咱們能夠定製短信呀、郵件呀的旋轉!
2.supportedInterfaceOrientations 方法通常是寫UIInterfaceOrientationMask方向,可是若是程序要兼容4.3如下的SDK(4.3如下的SDK必須是4.5如下的Xcode,不支持IOS6),那麼在用4.5如下的Xcode編譯的時候通不過!因此能夠用statusBarOrientation代替或者直接寫死數字!
- -(NSUInteger)supportedInterfaceOrientations{
- return [UIApplication sharedApplication].statusBarOrientation;
- }
3.通常都不建議在程序裏面直接調用 UIDeviceOrientation 的方向,而是用 UIInterfaceOrientation,他們之間是不一樣的!
- UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
- UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
看到嗎,左右是反的!Xcode圖形化設置方向也是以 UIInterfaceOrientation 爲準,就是home按鍵所在的方向
參考:
http://blog.csdn.net/totogogo/article/details/8002173
http://stackoverflow.com/questions/13200220/how-to-change-keyboard-orientation-in-ios6
http://blog.csdn.net/yiyaaixuexi/article/details/8035014
轉自:http://blog.csdn.net/zzfsuiye/article/details/8251060#t6