美文网首页iOS开发那些事iOS开发程序员
iOS 屏幕旋转,单个屏幕旋转的实现

iOS 屏幕旋转,单个屏幕旋转的实现

作者: WWest | 来源:发表于2016-04-22 14:14 被阅读3840次

    闲来无事研究了一下屏幕旋转的问题

    说到屏幕旋转问题不得先说一句,做项目尽量还是优先使用storyboard、IB因为有了autolayout的约束布局为基础再去做屏幕旋转需要的视图布局适配就相对来说简单容易很多。

    好了,闲话不多说,开始今天要说的问题。

    首先,想要实现单个屏幕旋转有两个重要的方法需要在viewcontroller里重写

    使用模式如下:

    //支持设备自动旋转

    - (BOOL)shouldAutorotate{

    returnYES;

    }

    //支持横竖屏显示

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations{

    returnUIInterfaceOrientationMaskAll;

    }

    如果你以为这样就会实现屏幕的旋转,那么你还是too young.

    想要在项目中使用屏幕旋转,需要注意一下几点

    1、首先确保总开关打开,要不然有可能项目崩溃。 例如你想让某个视图支持横屏,然后你这样写道

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations{

    returnUIInterfaceOrientationMaskLandscape;

    }

    这样就崩溃了,因为你项目根本就不支持横屏,言归正传,首先打开总开关(项目默认是打开的)

    target -> General -> device orientation

    打开开关你的项目就具备了屏幕旋转的权限。

    2、当你做了第一步后发现确实可以屏幕确实可以旋转了,但是好像屏幕旋转不受你控制,你需要的仅仅是某个或某几个页面能旋转,但是现在全都能旋转,这怎么办呢,现在我们需要了解一下旋转的机制。

    如果你想要支持屏幕旋转的controller为rootcontroller 那这样用,没毛病,但是一般情况下不会这样。

    如果你想要controller支持旋转,那么你需要保证它的上一级也支持相应的旋转,通常情况下我们的controller都是在NavController 的栈里边,所以一般的我们的controller的上一级都是NavController,所以我们要设置NavController屏幕旋转

    //支持设备自动旋转

    - (BOOL)shouldAutorotate{

    return YES;

    }

    //支持横竖屏显示

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations{

    return UIInterfaceOrientationMaskAll;

    }

    但是问题来了,有这么一种场景,NavController栈里边有好几个controller,可能你只需要某一个controller支持,而其他的不支持,最好的办法是获取栈最顶端的controller对旋转的支持状态,修改后如下

    //支持横竖屏

    - (BOOL)shouldAutorotate{

    return [self.viewControllers.lastObjectshouldAutorotate];

    }

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations{

    return [self.viewControllers.lastObjectsupportedInterfaceOrientations];

    }

    由于controller默认是开启的状态,所以每一个不需要旋转的屏幕的controller都要写上这么一句

    //屏幕旋转

    //支持设备自动旋转

    - (BOOL)shouldAutorotate{

    returnNO;

    }

    是不是麻烦?简单一点都办法就是创建一个controller的基类BaseViewController每个controller都继承BaseViewController ,在BaseViewController中重写- (BOOL)shouldAutorotate 方法默认关闭,这样做的坏处就是增加了项目代码的耦合度,因为BaseViewController是比较基础的,稍有改动就可能会对项目有很大的影响,利弊自己权衡。

    到这里你可能会想那项目中是以TabbarController 为Root controller的话怎么办?思考一下,其实TabbarController即为NavController 的上一级,根据NavController的逻辑我们可以写出下面的代码,一举解决这个问题。

    //支持横竖屏

    - (BOOL)shouldAutorotate{

    returnself.selectedViewController.shouldAutorotate;

    }

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations{

    return [self.selectedViewControllersupportedInterfaceOrientations];

    }

    说了这么多其实最主要的就是想清楚项目中controller的层层之间的关系,然后再去做相应的设置,最终你会实现你想要的。

    3、最后附上,进入某controller就让它旋转到某个方向的利器,经本人验证,可用,客官放心用

    NSNumber *value = [NSNumbernumberWithInt:UIInterfaceOrientationLandscapeRight];

    [[UIDevicecurrentDevice]setValue:valueforKey:@"orientation"];

    暂时就这么多内容,以后有新的内容会继续更新。

    PS: 很多人问我有没有demo,特此写了一个swift版的 demo,demo不重要重要的是理解屏幕旋转的逻辑

    demo地址:https://github.com/liutongchao/Orientation

    有问题欢迎指正以及互相探讨 -- LC.West

    相关文章

      网友评论

      • Ryan文濤:在做这个的时候,遇到点问题。我在基类来控制某个页面是否旋转,这个是可以做到。但是在已经设置不让旋转的界面,如果这时候旋转的话,状态栏会旋转了。无法限制住状态栏旋转,请问博主,这个应该怎么解决呢?
        d920e665d3d1:请问解决了 吗 我这也遇到了 有没有设么好的方案!
      • 伦敦乡下的小作家:楼主,我在基类里关闭了,想在需要旋转的子类里打开,但是重写的方法写错了,可否给个提示
        WWest:@伦敦乡下的小作家 这个代码不是重要的,主要是他们之间的作用关系。你如果想旋转必须在基类里打开才行。如果非要代码的话
        伦敦乡下的小作家:@WWest 楼主可否贴一下代码,参考下
        WWest:@伦敦乡下的小作家 写了没反应么?
      • 小酒窝_David:您好,我写了个demo,在ipone上面调用是可以的,在ipad上面,不执行category里面的方法,所以导致没法屏幕旋转,能帮忙看一下吗,QQ:350957516
        小酒窝_David:@WWest 问题解决了,谢谢你的回复
        WWest:@David_YangSong 这个我还没在iPad上开发过,不过你可以把代码发我看一下,QQ:413281269
      • 蓝色沙漏:今天看了好多文章,我的收获跟你写的一样,早看到这篇文章就好了。另外提点建议,可以用markdown 写,这样比较美观。
        WWest:@蓝色沙漏 哈哈,踩过几次坑才会印象深刻。这篇写的比较早,现在都已经在用markdown了。
      • 张云龙:研究了会,解决了我提出的几个问题,比较好的解决办法是每个页面都要支持旋转也就是:
        - (BOOL)shouldAutorotate {
        return YES;
        }
        当然这个不用自己写,系统默认,
        然后在每一个不需要旋转的页面都重写这个方法:
        - (BOOL)shouldAutorotate {
        UINavigationController *navi = self.selectedViewController;

        return navi.topViewController.shouldAutorotate;
        }
        这样就不会出现上面的问题了。
        但是present出来的页面还是会有问题,这个没时间研究太多,要么改成push的,要么把present的页面的适配做好,保证横屏的时候体验良好。
        WWest:@张云龙 非常感谢你提出的这些问题,抽空我会研究一下你遇到的这些问题,其实我写的这些就是一个解决问题的大概思路,到了具体问题上还要用相应的手段去处理,对于这篇文章能帮到你我也很高兴。
      • 张云龙:还发现一个问题,像6Plus、iPad这样的支持横屏启动的设备,横屏启动进入页面,而这个页面不能横屏,你这种做法也会导致横屏。
      • 张云龙:
        有2个问题,1、支持旋转的页面,在横屏模式下返回不支持的旋转的页面,不支持旋转的页面也横屏了;2、present的页面不受控制。
        WWest:@张云龙 对于第一个问题,我想到的是在页面返回前把device设置成竖屏(或是你想要的屏幕方向),能否成功有待验证。第二个问题抽空研究。很高兴你提出这些问题,更可贵的是你还提供了解决方法 :+1:
      • 张云龙:很准确,解决我的问题了,谢谢。
      • 5a38f7481378:和楼主采用同样的做法, 可以自由控制各个界面的横竖屏, 但是目前遇到状态栏不受控制, 当从某个横竖屏页面出来后, 这时外面的状态栏可以 翻转了. 还没找到好的解决方案, 若知晓,望不吝赐教.
        5a38f7481378:应该是 加在非keywindow上 会出现这种情况
        WWest:前几天我们讨论了这个问题,出现这种问题的原因是@无尾鸟 用了第三方提示框,而它是加载在window上的所以出现了状态栏旋转儿视图没旋转的原因。在这里记录一下,也为后来遇到这个问题的人提供一种思路,同时感谢这位童鞋!
        WWest:@无尾鸟 不太清楚你描述的问题,可以联系我,其实我也是在研究,咱们可以探讨探讨,我的资料里应该有我的QQ。
      • 587761a3c3fe:[[UIDevicecurrentDevice]setValue:valueforKey:@"orientation"];
        楼主你好,请问这个方法会被苹果拒吗?
        WWest:@隔壁老王家会敲代码的猫 有结果了告诉我一下哈,然后我给文章更新一下 :smile:
        587761a3c3fe:@就叫West怎么了 我去试试
        WWest:@隔壁老王家会敲代码的猫 这个我也在网上查了,好像不会被拒,但是具体的我还没实践过。

      本文标题:iOS 屏幕旋转,单个屏幕旋转的实现

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