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

之前項(xiàng)目中有個(gè)關(guān)于橫豎屏的需求,原本以為是很簡(jiǎn)單的事情,隨便一些就能解決,但結(jié)果發(fā)現(xiàn)事實(shí)并不是這樣。網(wǎng)上也搜索了很多關(guān)于橫豎屏旋轉(zhuǎn)的資料,但是很難發(fā)現(xiàn)卻不能滿足當(dāng)時(shí)項(xiàng)目中的需求,因?yàn)榫W(wǎng)上給的實(shí)現(xiàn)很多都是針對(duì)一個(gè)小demo而言,只是兩個(gè)簡(jiǎn)單的ViewController。而實(shí)際項(xiàng)目中一般都會(huì)涉及tabBarControll、navigationController,網(wǎng)上很多資料給的并不是很完全。所以就決定給這塊知識(shí)好好補(bǔ)充一下,記得當(dāng)時(shí)研究屏幕旋轉(zhuǎn)主要是參考ZFPlayer。實(shí)際屏幕旋轉(zhuǎn)會(huì)因?yàn)轫?xiàng)目結(jié)構(gòu),present,push等不同因素影響。今天就分多鐘情況說(shuō)明一下屏幕旋轉(zhuǎn)的實(shí)現(xiàn),并附帶上源碼下載地址。https://github.com/ZhengYaWei1992/ScreenRotate

======================第一種情況======================
常規(guī)帶有tabbarController的結(jié)構(gòu),首頁(yè)面都不能旋轉(zhuǎn),只有在某一個(gè)present進(jìn)去的子頁(yè)面可以旋轉(zhuǎn),注意這里是present,不是push。這兩種情況差別很大的。
首先,要想支持屏幕旋轉(zhuǎn),必選讓整個(gè)項(xiàng)目可以支持屏幕旋轉(zhuǎn),如下圖:

設(shè)置整個(gè)項(xiàng)目支持屏幕旋轉(zhuǎn)

a.首先在AppDelegate中添加一個(gè)全局屬性。

@property(nonatomic,assign)UIInterfaceOrientationMask allowRotation;

b.在AppDelegate.m中實(shí)現(xiàn)一個(gè)這樣一個(gè)方法。

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    if (_allowRotation == 1) {
      //支持橫豎屏,注意手機(jī)只能支持三個(gè)方向,這里不能寫成UIInterfaceOrientationMaskAll,否則會(huì)出現(xiàn)一些不可預(yù)料的問(wèn)題。只有iPad才支持四個(gè)方向。
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
    else
    {
        return (UIInterfaceOrientationMaskPortrait);
    }
}

c.在present進(jìn)去的子頁(yè)面中實(shí)現(xiàn)的代碼如下,設(shè)置支持橫豎屏。
在viewDidLoad:方法中添加如下代碼,設(shè)置屏幕支持旋轉(zhuǎn)。

AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    appDelegate.allowRotation = 1;

d.在離開這個(gè)界面之前我們要實(shí)現(xiàn)下面的代碼,設(shè)置只支持豎屏。

//離開的時(shí)候要再次設(shè)置
    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    appDelegate.allowRotation = 0;

e.如果想在屏幕旋轉(zhuǎn)后做一些適配,可以在下面這個(gè)方法中實(shí)現(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)入子頁(yè)面。雖然只是改變了一點(diǎn),但是實(shí)現(xiàn)代碼上差別很大的。
a.首先需要在tabbarController中實(shí)現(xiàn)以下兩個(gè)方法。這兩個(gè)方法的意思是將控制屏幕旋轉(zhuǎn)的主動(dòng)權(quán)都交給每個(gè)子頁(yè)面去實(shí)現(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)去的子頁(yè)面首先要重寫兩個(gè)系統(tǒng)方法,即和tabbarViewCotroller中相同的方法。設(shè)置支持旋轉(zhuǎn),支持三個(gè)旋轉(zhuǎn)方向

/是否可以旋轉(zhuǎn)
- (BOOL)shouldAutorotate
{
    return YES;
}
//支持的方向
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAllButUpsideDown;
}

c.但是僅僅實(shí)現(xiàn)上面的代碼是不夠的,這是如果在橫屏狀態(tài)下返回上一界面,會(huì)發(fā)現(xiàn)上一界面也是處于橫屏狀態(tài)。這和我們的初衷不一樣,我們想的是上一界面支持豎屏狀態(tài),不會(huì)受到子頁(yè)面的影響。解決辦法是在子頁(yè)面返回的時(shí)候?qū)崿F(xiàn)以下代碼。

//這里的目的是為了使返回時(shí),上一界面依然是豎屏
-(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.同樣,子頁(yè)面橫豎屏界面的適配同樣可以在以下這個(gè)方法中實(shí)現(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.其他不支持橫豎屏切換的控制器,都要實(shí)現(xiàn)以下方法。

   - (BOOL)shouldAutorotate
  {
      return NO;
  }
  //支持的方向
  -(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

======================第三種情況======================
這一次我們只讓present的子頁(yè)面,只支持橫屏,不支持豎屏。而其他控制器支持豎屏。實(shí)現(xiàn)起來(lái)很簡(jiǎn)單,只是在第一種情況中做一個(gè)小小的變動(dòng)。將第一種情況中的b步驟實(shí)現(xiàn)代碼改為如下代碼,其他實(shí)現(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)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容