屏幕橫豎屏旋轉(zhuǎn)系統(tǒng)整理

之前項目中有個關(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進(jìn)去的子頁面可以旋轉(zhuǎn),注意這里是present,不是push。這兩種情況差別很大的。
首先,要想支持屏幕旋轉(zhuǎn),必選讓整個項目可以支持屏幕旋轉(zhuǎn),如下圖:

設(shè)置整個項目支持屏幕旋轉(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進(jìn)去的子頁面中實現(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進(jìn)入子頁面。雖然只是改變了一點,但是實現(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進(jìn)去的子頁面首先要重寫兩個系統(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);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容