iOS 横竖屏切换

背景: 项目作为SDK接入到游戏项目中,切游戏是横屏,SDK只支持竖屏,在xCode11上编译包会出现一个瞬间的抖动问题

如何支持横竖屏切换

  • navigation中实现:
//// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead
- (UIInterfaceOrientationMask) supportedInterfaceOrientations{
    return [self.viewControllers.lastObject supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];
}

- (BOOL) shouldAutorotate {
    return [self.viewControllers.lastObject shouldAutorotate];
}
  • ViewController中实现:
//// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead
- (UIInterfaceOrientationMask) supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

- (BOOL) shouldAutorotate {
    return YES; //这里一定要是yes   如果是NO 就不支持自动切换,也不会继续调用另外两个方法了
}

--- 以上对xcode10及以前模拟器都没问题 ---

那么 xCode11 iOS 13 针对modalStyle推出了新特性,presentViewController的时候需要强制添加fullScreen的modalStyle,就会导致在横屏切换到竖屏的过程中出现一个诡异的抖动,那么问题来了,fullScreen到底做了什么,和之前的present 有和区别呢

这篇文章写的还是挺详细的

A->B 的情况下,用fullScreen的话 会调用presentedViewController的viewlayoutsubviews导致重新布局 有一个切换 闪一下


image.png

这里有两个方案

方案一

fullScreen模式下 在页面A里拦截一下这种情况下 拦截一下页面

方案二

使用overFullScreen 模式,但这个模式在横竖屏下会引发一系列连锁反应,系统不会帮你强制竖屏,当你presentingViewcontroller里实现了

- (BOOL) shouldAutorotate {
    return YES; 
}

相关代理之后,他能够根据当前window来实现页面的横竖屏转换,到这里 ,如果你的需求已经满足了,那么恭喜你,你已经成功了。下面内容可以忽略了~

因为用到了键盘和UIMenuController,而这两个东西并不在当前 application的keywindow上,下面可以看到,而我们要用到的键盘和Menu其实都是依附于UITextEffectsWindow上的


开启图层渲染

当我们使用overFullScreent的style,横屏进入页面的时候,系统其实并不会将 UITextEffectsWindow 这个window自动旋转为竖屏,系统判定当前仍然是横屏,name键盘和menu仍然是按照横屏的高度去计算的,这就会有问题,针对这种case,目前用了一个比较迂回(一个坑一个坑去填)的解决办法。

  • 在present的时机 调用竖屏:
- (void)rotationToDeviceOrientation {
    
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:@selector(setOrientation:)]];
    invocation.selector = NSSelectorFromString(@"setOrientation:");
    invocation.target = [UIDevice currentDevice];
    int initOrientation = UIDeviceOrientationPortrait; // 这里我们需要传的值是设备方向值
    [invocation setArgument:&initOrientation atIndex:2];
    [invocation invoke];

    /** 下面代码是为了当前导航栏旋转至设备方向*/
    [CCBaseNavigationController attemptRotationToDeviceOrientation];
}

  • 处理键盘 或 Menu 在横屏presentVC的时候,显示问题,这里会有一个小特点,就是当APP从后台切换会前台之后,会触发系统的刷新,这个时候能够刷新,所以我们这里处理的就是这个极端case的UI颠倒显示的问题

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(adjustKeyboardWindow) name:UIApplicationDidBecomeActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];

/*
 这是一处及其恶心的代码,为了适配iOS13横竖屏切换的问题,
 iOS13上用 overfullScreen present的VC,进入页面
 UITextEffectsWindow window不会切换竖屏,所以这里需要暴力扭转一下
 心虚的说一下  不知道会有啥坑  见招拆招吧~
 **/
- (void)adjustKeyboardWindow {
    if (@available(iOS 13.0, *)) {
        NSUInteger windowCount = [[[UIApplication sharedApplication] windows] count];
        if(windowCount < 2) {
            return;
        }
        UIWindow *keyboardWindow = nil;
        if(windowCount >= 2)//ios9以上,UIRemoteKeyboardWindow
        {
           keyboardWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
        }
        if (keyboardWindow.wind_width > keyboardWindow.wind_height) {
            keyboardWindow.transform = CGAffineTransformMakeRotation(-M_PI_2);
            self.isAdjustKeyboardFrame = YES;
        } else {
            keyboardWindow.transform = CGAffineTransformMakeRotation(0);
            self.isAdjustKeyboardFrame = NO;
        }
        keyboardWindow.bounds = CGRectMake(0, 0, WindCS_SCREEN_MIN_LENGTH, WindCS_SCREEN_MAX_LENGTH);
    }
    
}



- (void)deviceOrientationDidChange:(NSNotification *)notificationn {
    [self adjustKeyboardWindow];
}


以上希望能够帮助到有需要的朋友,有问题进一步沟通~

你可能感兴趣的:(iOS 横竖屏切换)