項目APP中總會遇到某些頁面需要橫屏展示珊燎,其他頁面默認豎屏展示。所以總結了一套自己使用的橫豎屏方法遵湖。
首先我查看UIKit的Api文檔發(fā)現(xiàn)有一個UIViewController的分類UIViewControllerRotation
里面有幾項是:
// 當前Controller是否支持旋轉延旧,YES -- 可以旋轉 NO -- 不支持旋轉 , 默認是YES(iOS 6.0之后可用)
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0);
// 當前Controller支持的旋轉方向迁沫,默認是UIInterfaceOrientationMaskAll(iOS 6.0之后可用)
- (UIInterfaceOrientationMask)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0);
// 當前Controller默認的方向,使用present方式彈出時可用(iOS 6.0之后可用)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0);
只要在需要旋轉的控制器里面重寫這幾個方法近弟,就能實現(xiàn)當前控制器的橫豎屏旋轉了挺智。
當然,首先TARGETS的配置文件需要設置“Device Orientation”配置支持的設備方向。(某些頁面需要橫屏掐頁面需要豎屏的話迫摔,需要勾選上 “Landscape Left” “Landscape Right”泥从,不過具體需要根據(jù)需求確定)
似乎事情朝著很好的預期進發(fā),但是事實并非如此......(你會發(fā)現(xiàn)即使重寫了這些方法纱烘,頁面并不會按照你的想法去旋轉)
一番查找祈餐,終于找到了原因:
我們APP一般的形式是window的rootViewController一般是UITabBarController,然后UITabBarController的viewControllers一般是多個導航欄UINavigationController哺壶。(或者window的rootViewController是UINavigationController)等等方式蜒谤。
那么要控制window的旋轉山宾,需要從window的rootViewController開始控制旋轉鳍徽,但是系統(tǒng)的UITabBarController默認的旋轉都是打開的阶祭,而且是所有方向都支持,那么我們只能從繼承自UITabBarController的類開始濒募,一級一級的去處理重寫旋轉方向支持。然后我們需要由控制器決定自己是否需要旋轉齿诉,不影響其他頁面的旋轉培他,所以就要一級一級的告知window當前控制器是否需要旋轉。所以我的做法是這樣的:
繼承自UITabBarController的類俊扳,重寫這幾個系統(tǒng)方法:
// 支持設備自動旋轉猛遍,由selectedViewController決定是否支持旋轉
- (BOOL)shouldAutorotate{
return [self.selectedViewController shouldAutorotate];
}
// 支持旋轉方向号坡,由selectedViewController決定旋轉方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return [self.selectedViewController supportedInterfaceOrientations];
}
// 當前控制器默認的屏幕方向梯醒,由selectedViewController決定旋轉方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
然后我們App一般的selectedViewController都是UINavigationController,所以在繼承自UINavigationController的類里面同樣重寫這幾個系統(tǒng)方法:
// 支持設備自動旋轉畜隶,由topViewController決定是否要旋轉
- (BOOL)shouldAutorotate{
return [self.topViewController shouldAutorotate];
}
// 支持旋轉方向号胚,由topViewController決定旋轉方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return [self.topViewController supportedInterfaceOrientations];
}
// 當前控制器默認的屏幕方向,由topViewController決定旋轉方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
一般我們控制器都有一個基類(例如BaseViewController)箱亿,所有的控制器都繼承自這個基類(BaseViewController)弃秆,然后在基類中同樣重寫這幾個系統(tǒng)方法:
// 這里讓所有控制器都支持旋轉
- (BOOL)shouldAutorotate{
return YES;
}
// 這里寫默認app的方向,一般app大多都是只支持豎屏脑豹,所以這里return一個UIInterfaceOrientationMaskPortrait值
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
// 這里寫當前控制器默認的屏幕方向锈至,一般app大多都是只支持豎屏,所以這里return一個UIInterfaceOrientationPortrait值
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationPortrait;
}
這里要記錄一下
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
這個方法的用途,這個方法主要用于present方式彈出的視圖器作用们拙,例如A push B push C 阁吝,這樣都是push操作的話,這個方法其實并沒有作用突勇。但是 A push B 然后 B present C,此時重寫C控制器里面的這個方法埂奈,就會體現(xiàn)出作用了定躏,present出來的控制器默認是彈出來是朝著什么方向由這個方法決定芹敌,當然這個方法這個方法要配合supportedInterfaceOrientations方法一起垮抗,這兩個返回值要一致(例如preferredInterfaceOrientationForPresentation返回值是UIInterfaceOrientationLandscapeRight右側,那么supportedInterfaceOrientations返回值也要是UIInterfaceOrientationMaskLandscapeRight或者UIInterfaceOrientationMaskLandscape或者UIInterfaceOrientationMaskAllButUpsideDown)液茎,否則就crash了辞嗡。
接著就是正常的碼代碼。楚里。猎贴。一直碼到某一個控制器需要支持旋轉,此時在這個控制器里面重寫下面的方法达址,這樣這個控制器就可以根據(jù)手機的重力感應而旋轉方向了
// 這里重寫此方法趁耗,決定當前控制器要支持的旋轉方向,返回值因項目而定
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
但是有些情況下我們的app在跳轉的時候就需要從一個豎屏的控制器VcA push到一個只支持橫屏的控制器VcB满葛,那么只重寫這些東西是無法實現(xiàn)push VcB之后就是橫屏罢屈,只會是豎屏,然后手機橫著放才能轉到橫屏缠捌,此時我們就需要在VcB內(nèi)強制把屏幕旋轉到橫屏,這樣就實現(xiàn)了從豎屏VcA push到一個橫屏的控制器VcB谊却,強制旋轉方法如下:
// 先置為Unknown狀態(tài)哑芹,讓系統(tǒng)不知道當前屏幕狀態(tài)
NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
// 然后將orientation的值置為右側,這樣系統(tǒng)就會更新屏幕方向蹦魔,轉到右側
NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
同時需要配合重寫supportedInterfaceOrientations方法,才能生效乒躺,否則容易crash低缩。
這樣push過去的VcB就是一個橫屏的頁面,但是如果還有在下一級的push VcC咆繁,此時需要將視圖轉回來玩般,否則下一級頁面會出現(xiàn)雖然給定了豎直方向,但是保留了上一級頁面的方向坏为,此時同樣使用這些代碼:
// 先置為Unknown狀態(tài)匀伏,讓系統(tǒng)不知道當前屏幕狀態(tài)
NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
// 然后將orientation的值置為豎直,這樣系統(tǒng)就會更新屏幕方向够颠,轉到豎直方向
NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
這一段代碼可以放在VcB的viewWillDisappear或者寫在VcC的viewWillAppear都可以的履磨。
還有另外一種方法,如果你的項目沒有基類剃诅,項目已經(jīng)成型了,去改基類的話如果類比較少的話,還好控制一點如筛,但是如果項目比較大抒抬,讓后要一個一個類的去添加基類,耗時耗力擦剑,那么可以使用AppDelegate來控制旋轉。
在AppDelegate的.h文件中添加一個屬性
在AppDelegate的.m文件里面重寫:
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return self.interfaceOrientationMask;
}
指定初始值豎直方向UIInterfaceOrientationMaskPortrait:
然后在需要旋轉的頁面:
記得在消失的時候將“旋轉開關”置為初始狀態(tài)UIInterfaceOrientationMaskPortrait爬坑,不然其他頁面將會支持旋轉了盾计,那就不是我們想要的效果了赁遗。
再配合
NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
就可以隨心所欲的旋轉了。哭尝。剖煌。