美文网首页
iOS 模态实现单个控制器横屏,其他控制器保持竖屏

iOS 模态实现单个控制器横屏,其他控制器保持竖屏

作者: 翻滚的炒勺2013 | 来源:发表于2018-06-17 22:33 被阅读144次
    景甜.jpg

    前言

    去年的时候有一个项目需求,其中单个控制器跳转进去横屏,其他控制器保持横屏,当初做的时候觉得很简单,找了下API用模拟器试了下没问题就没当回事,后来真机测试的时候傻眼了,模拟器可以通过测试,真机有时候能横屏有的时候不行,而且有时候进入横屏的时候也会布局错乱,在网上找了许多demo都没有好的办法,后来借鉴群里大神的demo算是完美实现了横屏,可以大神用的语言是swift.项目时间紧当时也没有总结,现在刚好有空把项目找出来把里面的代码剥出来,这里暂时只讨论present实现横屏.


    • 模拟器能够横屏,真机偶尔不能横屏
    • 进去控制器能横屏,返回之前的控制器还是横屏
    • 进去控制器是横屏,锁定屏幕解锁之后返回上个控制还是横屏

    API

    UIDeviceOrientation

    是设备的物理方向,不能写入只能读取

      UIDeviceOrientationUnknown,
      UIDeviceOrientationPortrait,            // Device oriented vertically, home button on the bottom
      UIDeviceOrientationPortraitUpsideDown,  // Device oriented vertically, home button on the top
      UIDeviceOrientationLandscapeLeft,       // Device oriented horizontally, home button on the right
      UIDeviceOrientationLandscapeRight,      // Device oriented horizontally, home button on the left
      UIDeviceOrientationFaceUp,              // Device oriented flat, face up
      UIDeviceOrientationFaceDown             // Device oriented flat, face down
    
    UIInterfaceOrientation

    视图的方向,他和statusBar的方向是一致的

    typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
         /** 未知方向 */
        UIInterfaceOrientationUnknown            = UIDeviceOrientationUnknown,
         /** 竖直 */
        UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
         /** 上下翻转 */
        UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
          /** 向左旋转 */
        UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
          /** 向右旋转 */
        UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
    } __TVOS_PROHIBITED;
    
    

    UIDeviceOrientation与UIInterfaceOrientation是两个互不相干的属性。
    其中一个并不会随另外一个变化而变化。但大多数情况下,两者会一起出现,主要是为了达到视觉的统一。
    注意:
    UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
    UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
    两者是相反的

    UIInterfaceOrientationMask

    这是ios6之后新增的一组枚举值,使用组合时更加方便,使用时根据返回值类型选择正确的格式,避免可能出现的bug

    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),
    
    

    如果想横屏在Targets应该去勾选对应的选项


    image.png

    想让控制切换横竖屏主要是这三个方法

    /** Interface的方向是否会跟随设备方向自动旋转,如果返回NO,后两个方法不会再调用 */
    - (BOOL)shouldAutorotate {
        return YES;
    }
    /** 返回直接支持的方向 */
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
        return 返回你想要的方向;
    }
    /** 返回最优先显示的屏幕方向 */
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
        return  返回你想要的方向;
    }
    

    注意:如果在targets中只设置了竖屏那么方法preferredInterfaceOrientationForPresentation和supportedInterfaceOrientations无效

    代码

    在要横屏的控制器写下面的方法

    - (BOOL)shouldAutorotate {
        return NO;
    }
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
           return UIInterfaceOrientationMaskLandscapeRight;
    }
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
            return UIInterfaceOrientationLandscapeRight;
    }
    
    

    加入一个返回的事件

    • (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
      [self dismissViewControllerAnimated:YES completion:nil];
      }

    接下来看效果


    Untitled.gif

    看似好像解决了问题,其实并没有,在进入横屏页锁屏再解锁返回上个控制器就会出现布局错误
    原因是返回上一页时,或者在当前页面不不支持的方向的上一页进来时,不能立即达到预期状态,需要设备方向更换一次才能恢复正常。

    这是在dismis返回之前加入以下代码强制设置设备为竖屏即可解决问题

       NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
        [[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
        
        NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
        [[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
    

    END

    参考链接

    相关文章

      网友评论

          本文标题:iOS 模态实现单个控制器横屏,其他控制器保持竖屏

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