1、iOS开发中一般情况只会用到竖屏,但有些app 的个别页面却要变成横屏,所以在很竖屏的切换就是一个经常用到的问题。
一般情况下会用到一下几个方法
// 是否支持屏幕旋转
- (BOOL)shouldAutorotate {
return YES;
}
// 设置特殊的界面支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
// 当前设备支持的方向(横屏方向)
return UIInterfaceOrientationMaskLandscape;
}
// 当前设备的屏幕方向
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
// 当前设备的屏幕方向(home 键在右边)
return UIInterfaceOrientationLandscapeRight;
}
如果有 UINavigationController 或者是 UITabBarController 等这些容器控制器的时候,上面方法就没有了,底层控制器不是一般的 UIViewController
所以需要在 UINavigationController 里面实现
// 是支持屏幕旋转
- (BOOL)shouldAutorotate {
return [self.visibleViewController shouldAutorotate];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return [self.visibleViewController supportedInterfaceOrientations];
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.visibleViewController preferredInterfaceOrientationForPresentation];
}
和在 UITabBarController 里面实现
// 是支持屏幕旋转
- (BOOL)shouldAutorotate {
return [self.selectedViewController shouldAutorotate];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return [self.selectedViewController supportedInterfaceOrientations];
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
2、但是这回出现的问题是,比如我直接跳转倒膜个页面,需要将当前的竖屏变为横屏,直接用上面的方法是行不通的。所以需要使用到 强制横竖屏。在强制很竖屏前必须要明确当前设备到底支持那些方向,然后才能让你的设备支持具体的方向。这些方法写在 viewDidLoad 里面没有,一般写在viewWillAppear:里面
// 强制旋转屏幕到所需要的方向
- (void)resetInterfaceOrientation:(UIInterfaceOrientation)Orientation {
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];
}
}
// 强制旋转屏幕方向
- (void)resetInterfaceOrientation:(UIInterfaceOrientation)Orientation {
//
NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
//
NSNumber *orientationTarget = [NSNumber numberWithInt:Orientation];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
}
3、其他问题比如点击某个按钮,或者触发某个事件后需要强制旋转屏幕,同理也需要先去确定设备所支持的方向。这样才可以相应设备的当前方向。
// (1)横屏方法,先确定所需要支持的方向
self.supportLandscape = YES;
// 只支旋转
- (BOOL)shouldAutorotate {
return YES;
}
// (2)然后在确定支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
if (self.supportLandscape) {
return UIInterfaceOrientationMaskLandscape; //左右方向
} else {
return UIInterfaceOrientationMaskPortrait; //竖直方向
}
}
//(3)最后 强制旋转屏幕到所需要的方向
- (void)resetInterfaceOrientation:(UIInterfaceOrientation)Orientation {
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;
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
}
4、还可以通过切换window的rootViewController 来实现横竖屏,用此次方法来实现横竖屏是不需要官切换前后的设备放下过是不是需要还原。这种方法需要在切换rootViewController之前讲原来的rootViewController存储起来,以保证还原的时候可以还原原来的家控制器。
// 切换rootViewControler
ZHHorzonViewController *horVC = [[ZHHorzonViewController alloc] init];
horVC.rootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
[UIApplication sharedApplication].keyWindow.rootViewController = horVC;
//还原rootVC
[UIApplication sharedApplication].keyWindow.rootViewController = self.rootVC;
5、和全局控制,全局控制是通过 appdelegate 来实现的,向什么有 UINavigationController 和 UITabBarController 等的控制器一样的处理
先为 appdelegate 注册属性用于确定方向
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (self.allowRotation == YES) {
//横屏
return UIInterfaceOrientationMaskLandscape;
}else{
//竖屏
return UIInterfaceOrientationMaskPortrait;
}
}
然后在需要切换的地方先设置全局方向
// 全局控制
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
delegate.allowRotation = YES;
最后在改变方向
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 = UIInterfaceOrientationLandscapeLeft;
// 从2开始是因为0 1 两个参数已经被selector和target占用
[invocation setArgument:&val atIndex:2];
[invocation invoke];
}
当还原的时候,需要先控制支持的方向
// 全局控制
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
delegate.allowRotation = NO;
// 还原为竖屏
NSNumber *orientationUnknown = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:orientationUnknown forKey:@"orientation"];
NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];