公司App里面有个需求,即所有界面都是竖屏,且不允许横屏切换,唯独有一个播放视频的界面允许横屏,大家都知道视频播放适配最大的播放屏幕那样是最好的。从网上多方查找资料,总结如下:
-
最终,根据此需求处理如下: 首先,确保App本身应该允许转屏切换:
-
我的App里面UITabBarController是根视图控制器,所以首先创建一个UITabBarController的子类,并设定允许转屏:
(这些要放在根视图控制器里面, 如果你的应用根视图是UINavigationController, 就放在那里面就好)
#pragma mark 转屏方法重写
//返回支持的方向
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return [self.viewControllers.firstObject supportedInterfaceOrientations];
}
//返回YES,可以根据重力感应自动旋转
-(BOOL)shouldAutorotate{
return self.viewControllers.firstObject.shouldAutorotate;
}
3.接着,我的tabbarController里面每个子控制器又都是UINavigationController进行界面push切换的,所以首先创建一个UINavigationController的子类,并设定允许转屏:
//self.topViewController是当前导航显示的UIViewController,这样就可以控制每个UIViewController所支持的方向啦!
-(BOOL)shouldAutorotate{
return [self.topViewController shouldAutorotate];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return [self.topViewController supportedInterfaceOrientations];
}
4.在BaseViewController上重写,指定界面的为竖屏:
- (BOOL)shouldAutorotate {
return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
5.需要横屏界面重写BaseViewController方法,指定当前界面为横屏,不允许自动旋转
// 返回NO,不根据重力感应自动旋转
- (BOOL)shouldAutorotate {
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
//返回优先方向
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight;
}
这样的设计理念就是RootVC 去询问NavigationController 询问BaseViewController 询问具体的ViewController。整体下来就做到了只需在特定需求界面重写转屏方法。
注意:跳转到播放器要使用模态进来, 用Push不会横屏。具体原因不清楚,有了解的麻烦告知一下
[self presentViewController:playerVC animated:YES completion:nil];
###总结
- 如果需求仅仅是少量几个控制器横屏显示,可以定义一个UIViewController的子类作为你的BaseViewController,其他控制器继承自他就好了,只在需要横屏的重写那是3个方法,不用每个控制器都写
- demo地址
###还有一种比较霸道的私有方法,方便实用
setOrientation 在3.0以后变为私有方法了,不能直接去调用此方法,否则就是审核被拒。
不能直接调用,但是可以间接的去调用,下面的方法就是利用 NSInvocation 去间接调用,多次验证不会被拒,放心!听说还可以利用KVO间接调用,感兴趣的可以试一下
#pragma - 屏幕屏幕方向
- (void)interfaceOrientation:(UIInterfaceOrientation)orientation {
// arc下
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
SEL selector = NSSelectorFromString(@"setOrientation:");
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:[UIDevice currentDevice]];
int val = orientation;
//从2开始是因为0 1 两个参数已经被selector和target占用
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
}
## 直接在当前控制器调用就行,支持push方式的控制器跳转
- (void)viewDidLoad {
[super viewDidLoad];
[self interfaceOrientation:UIInterfaceOrientationLandscapeRight];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self interfaceOrientation:UIInterfaceOrientationPortrait];
}