美文网首页程序员iOS Developer
iOS竖屏App强制某一部分横屏

iOS竖屏App强制某一部分横屏

作者: Fly_Sunshine_J | 来源:发表于2017-08-04 18:08 被阅读427次

    前言

    很长时间没有更新简书,原因不多说(因为懒),最近比较清闲,想起来写一篇文章来说一下iOS横竖屏轻松切换的过程。 有些需求整体的App只支持竖屏,但是只需要某一部分页面支持横屏,许多的视频类的App都要在竖屏的情况下进行横屏播放,当然还有很多的奇葩需求要横屏来进行实现。

    废话少说,进主题

    创建项目,App的方向只需要勾选Portrait就行(其实可以不用勾,但是能有几个项目中不勾的呢,我们还是勾上吧)。

    勾选方向
    前面说可以不勾选因为我们要在AppDelegate中,重写这个方法, 应用程序启动的时候会调用这个方法来给App所需要的屏幕方向:
    - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
        if([ScreenDirectionManager manager].islandscape) {
            return UIInterfaceOrientationMaskLandscape;
        }else {
            return UIInterfaceOrientationMaskAll;
        }
        
    }
    

    其中UIInterfaceOrientationMask是一个NS_OPTIONS, 我们可以随意组合,虽然其中有一些组合好的,但是万一不满足产品的奇葩需求呢,对不对,要提前留一手。

    typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
        UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
        UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
        UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
        UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
        UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
        UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
        UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
    } __TVOS_PROHIBITED;
    

    意思内容不用多解释,应该都能知道什么意思。

    其中ScreenDirectionManager这个类控制屏幕是否横屏,是一个单例就一个属性是否需要横屏,比较简单。

    @interface ScreenDirectionManager : NSObject
    
    + (instancetype)manager;
    
    @property (nonatomic, assign, getter=islandscape) BOOL landscape;
    
    @end
    

    如果你的App不包括导航栏(UINaviagtionController)或者(UITabbarController),你只需要重写UIViewController里面的三个方法就行,这三个方法是:

    //  返回bool值,决定Controller是否自动旋转
    -(BOOL)shouldAutorotate
    //返回一个Controller支持的方向
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations
    //返回现在正在显示的用户界面方向
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
    

    但是一般的应用至少有个导航栏吧,所以呢你还需要自定义导航栏(UINavigationController),然后在导航栏里面重写这三个方法,如果不重写,就无法达到你想要的效果,感觉就像这个屏幕方向具有传递的性质。但是我感觉UITabbarController的情况应该少数,我这里不讨论这个情况,下次有空再补上,但是我感觉原理应该是一样的,有兴趣的可以自己试一下。

    导航栏的屏幕方向和旋转性质要和导航栏最上层的Controller保持一致,所以自定义导航栏重写的三个方法是这样的:

    -(BOOL)shouldAutorotate {
        return [[self.viewControllers lastObject] shouldAutorotate];
    }
    
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
        return [[self.viewControllers lastObject] supportedInterfaceOrientations];
    }
    
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
        return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
    }
    

    ViewController中,重写上述的三个方法,返回自己想要的方向,那个改Controller只能是返回的方向,例如:

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskPortrait;
    }
    
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
        return UIInterfaceOrientationPortrait;
    }
    
    - (BOOL)shouldAutorotate {
        return YES;
    }
    

    在第二个页面中,也就是跳转的页面中,重写上述的三个方法,返回自己想要的方向,然后在viewWillAppear方法中设定将单例的属性方向改变,然后根据UIDeviceorientation这个属性,根据KVC,强制设置方向,如下;

    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        [ScreenDirectionManager manager].landscape = YES;
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
    //写这句话的目的是保证后面的一句话产生作用,具体不明白为什么,但是不加上会出现bug。有明白的可以告知一下。
            [[UIDevice currentDevice] setValue:@(UIDeviceOrientationUnknown) forKey:@"orientation"];
            [[UIDevice currentDevice] setValue:@(UIDeviceOrientationLandscapeLeft) forKey:@"orientation"];
        }
        
    }
    
    

    还需要在viewWillDisappear中,将单例的横竖屏属性改变回来,因为supportedInterfaceOrientations这个方法会触发AppDelegate中的方向支持方法。

    结论

    文章描述的不太清楚的,欢迎留言讨论。Demo

    相关文章

      网友评论

        本文标题:iOS竖屏App强制某一部分横屏

        本文链接:https://www.haomeiwen.com/subject/ruqblxtx.html