背景: 项目作为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];
}
以上希望能够帮助到有需要的朋友,有问题进一步沟通~
网友评论