之前項目中有個關(guān)于橫豎屏的需求叶撒,原本以為是很簡單的事情紊搪,隨便一些就能解決卡儒,但結(jié)果發(fā)現(xiàn)事實并不是這樣田柔。網(wǎng)上也搜索了很多關(guān)于橫豎屏旋轉(zhuǎn)的資料俐巴,但是很難發(fā)現(xiàn)卻不能滿足當(dāng)時項目中的需求,因為網(wǎng)上給的實現(xiàn)很多都是針對一個小demo而言硬爆,只是兩個簡單的ViewController欣舵。而實際項目中一般都會涉及tabBarControll、navigationController摆屯,網(wǎng)上很多資料給的并不是很完全邻遏。所以就決定給這塊知識好好補充一下,記得當(dāng)時研究屏幕旋轉(zhuǎn)主要是參考ZFPlayer虐骑。實際屏幕旋轉(zhuǎn)會因為項目結(jié)構(gòu)准验,present,push等不同因素影響廷没。今天就分多鐘情況說明一下屏幕旋轉(zhuǎn)的實現(xiàn)糊饱,并附帶上源碼下載地址。https://github.com/ZhengYaWei1992/ScreenRotate
======================第一種情況======================
常規(guī)帶有tabbarController的結(jié)構(gòu)颠黎,首頁面都不能旋轉(zhuǎn)另锋,只有在某一個present進去的子頁面可以旋轉(zhuǎn),注意這里是present狭归,不是push夭坪。這兩種情況差別很大的。
首先过椎,要想支持屏幕旋轉(zhuǎn)室梅,必選讓整個項目可以支持屏幕旋轉(zhuǎn),如下圖:
a.首先在AppDelegate中添加一個全局屬性疚宇。
@property(nonatomic,assign)UIInterfaceOrientationMask allowRotation;
b.在AppDelegate.m中實現(xiàn)一個這樣一個方法亡鼠。
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (_allowRotation == 1) {
//支持橫豎屏,注意手機只能支持三個方向敷待,這里不能寫成UIInterfaceOrientationMaskAll间涵,否則會出現(xiàn)一些不可預(yù)料的問題。只有iPad才支持四個方向榜揖。
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else
{
return (UIInterfaceOrientationMaskPortrait);
}
}
c.在present進去的子頁面中實現(xiàn)的代碼如下勾哩,設(shè)置支持橫豎屏。
在viewDidLoad:方法中添加如下代碼,設(shè)置屏幕支持旋轉(zhuǎn)举哟。
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.allowRotation = 1;
d.在離開這個界面之前我們要實現(xiàn)下面的代碼思劳,設(shè)置只支持豎屏。
//離開的時候要再次設(shè)置
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.allowRotation = 0;
e.如果想在屏幕旋轉(zhuǎn)后做一些適配炎滞,可以在下面這個方法中實現(xiàn)敢艰。
//在這里布局橫豎屏的UI
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
self.view.backgroundColor = [UIColor whiteColor];
NSLog(@"垂直");
}else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight || toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
self.view.backgroundColor = [UIColor redColor];
NSLog(@"橫向");
}
}
======================第二種情況======================
再看第二種情況,和第一種情況基本類似册赛,只是將present方式改成push進入子頁面钠导。雖然只是改變了一點震嫉,但是實現(xiàn)代碼上差別很大的。
a.首先需要在tabbarController中實現(xiàn)以下兩個方法牡属。這兩個方法的意思是將控制屏幕旋轉(zhuǎn)的主動權(quán)都交給每個子頁面去實現(xiàn)票堵。
//是否支持旋轉(zhuǎn)
-(BOOL)shouldAutorotate{
UINavigationController *navC = self.selectedViewController;
UIViewController *currentVC = navC.visibleViewController;
return [currentVC shouldAutorotate];
}
//支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
UINavigationController *navC = self.selectedViewController;
UIViewController *currentVC = navC.visibleViewController;
return [currentVC supportedInterfaceOrientations];;
}
b.push進去的子頁面首先要重寫兩個系統(tǒng)方法,即和tabbarViewCotroller中相同的方法逮栅。設(shè)置支持旋轉(zhuǎn)悴势,支持三個旋轉(zhuǎn)方向
/是否可以旋轉(zhuǎn)
- (BOOL)shouldAutorotate
{
return YES;
}
//支持的方向
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
c.但是僅僅實現(xiàn)上面的代碼是不夠的,這是如果在橫屏狀態(tài)下返回上一界面措伐,會發(fā)現(xiàn)上一界面也是處于橫屏狀態(tài)特纤。這和我們的初衷不一樣,我們想的是上一界面支持豎屏狀態(tài)侥加,不會受到子頁面的影響捧存。解決辦法是在子頁面返回的時候?qū)崿F(xiàn)以下代碼。
//這里的目的是為了使返回時担败,上一界面依然是豎屏
-(void)viewWillDisappear:(BOOL)animated{
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 = UIInterfaceOrientationPortrait;
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
}
d.同樣昔穴,子頁面橫豎屏界面的適配同樣可以在以下這個方法中實現(xiàn)。
//在這里布局橫豎屏的UI
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
self.view.backgroundColor = [UIColor whiteColor];
NSLog(@"垂直");
}else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight || toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
self.view.backgroundColor = [UIColor blackColor];
NSLog(@"橫向");
}
}
e.其他不支持橫豎屏切換的控制器提前,都要實現(xiàn)以下方法吗货。
- (BOOL)shouldAutorotate
{
return NO;
}
//支持的方向
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
======================第三種情況======================
這一次我們只讓present的子頁面,只支持橫屏狈网,不支持豎屏宙搬。而其他控制器支持豎屏。實現(xiàn)起來很簡單孙援,只是在第一種情況中做一個小小的變動害淤。將第一種情況中的b步驟實現(xiàn)代碼改為如下代碼扇雕,其他實現(xiàn)代碼和第一種情況相同拓售。
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (_allowRotation == 1) {
NSLog(@"appDelegate橫屏");
return UIInterfaceOrientationMaskLandscapeRight;
}
else
{ NSLog(@"appDelegate豎屏");
return (UIInterfaceOrientationMaskPortrait);
}
}