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

2018-06-17  本文已影响144人  翻滚的炒勺2013
景甜.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;
}

加入一个返回的事件

接下来看效果


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

参考链接

上一篇下一篇

猜你喜欢

热点阅读