IOS横竖屏切换是一个很纠结的问题,之前项目中用到了,花了长时间查阅资料以及研究,才找到了一个相对靠谱的解决方案,该方案可以处理IOS9系统以上的屏幕翻转,至于IOS9一下的系统,还没有测试过。
为了过程的讲解,我先给出一个应用的需求:整个界面就显示一个按钮,当点击这个按钮的时候,界面能从竖屏切换到横屏,当再次点击的时候,又能从横屏切换到竖屏,之后点击循环往复。为了达到这样的需求,我们首先新建一个IOS工程。
在工程创建之后,需要设置应用支持的屏幕旋转方向。默认情况下,IOS支持四个方向的旋转,即Portrait、UpsideDown、LandscapeLeft、LandscapeRight。
可以在工程配置的General下面可以看到,也可以在info.plist里面进行配置
info.plist
配置好应用支持的屏幕旋转类型之后,接下来就需要在代码中配置横竖屏的情况。
这里很关键的一点是一定要配置rootViewController的横竖屏情况,特别是当rootViewController是NavigationViewController的时候,所以一定要对作为rootViewController的controller进行重写。下面给出的代码是对NavigationViewController的重写。
//
// RotateNavigationController.h
// RotateScreen
//
// Created by obo on 16/1/28.
// Copyright © 2016年 obo. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RotateNavigationController : UINavigationController
@property (nonatomic)UIInterfaceOrientation interfaceOrientation;
@property (nonatomic)UIInterfaceOrientationMask interfaceOrientationMask;
@end
//
// RotateNavigationController.m
// RotateScreen
//
// Created by obo on 16/1/28.
// Copyright © 2016年 obo. All rights reserved.
//
#import "RotateNavigationController.h"
@implementation RotateNavigationController
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController {
self = [super initWithRootViewController:rootViewController];
if (self) {
self.interfaceOrientation = UIInterfaceOrientationPortrait;
self.interfaceOrientationMask = UIInterfaceOrientationMaskPortrait;
}
return self;
}
//设置是否允许自动旋转
- (BOOL)shouldAutorotate {
return YES;
}
//设置支持的屏幕旋转方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return self.interfaceOrientationMask ;
}
//设置presentation方式展示的屏幕方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.interfaceOrientation ;
}
@end
重写实现NavigationViewController的shouldAutorate和supportedInterfaceOrientations这两个关键的方法,网上大部分建议都是让shouldAutorate返回NO,但实际上,返回NO的话,则会导致同一个界面的不能进行翻转,所以这里还是需要返回YES的。需要注意的是,interfaceOrientationMask和interfaceOrientation的初始值需要在controller初始化的时候进行赋值的,取值按照应用刚启动的时候屏幕翻转方向来设定。
之后,将这个NavigationViewController作为应用启动的rootViewController,在AppDelegate中的调用如下:
//
// AppDelegate.m
// RotateScreen
//
// Created by obo on 16/1/28.
// Copyright © 2016年 obo. All rights reserved.
//
#import "AppDelegate.h"
#import "RotateNavigationController.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
RotateNavigationController *rotateNavigationController = [[RotateNavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
[rotateNavigationController setNavigationBarHidden:YES];
self.window.rootViewController = rotateNavigationController;
return YES;
}
@end
其中,ViewController是要显示的第一个界面,其内容的代码如下:
//
// ViewController.m
// RotateScreen
//
// Created by obo on 16/1/28.
// Copyright © 2016年 obo. All rights reserved.
//
#import "ViewController.h"
#import "RotateNavigationController.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initViews];
}
- (void)initViews {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 150, 100, 80)];
[button setTitle:@"切换横竖屏" forState:UIControlStateNormal];
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:@selector(clickToRotate) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
- (void)clickToRotate {
RotateNavigationController *navigationController = (RotateNavigationController *)self.navigationController;
//切换rootViewController的旋转方向
if (navigationController.interfaceOrientation == UIInterfaceOrientationPortrait) {
navigationController.interfaceOrientation = UIInterfaceOrientationLandscapeRight;
navigationController.interfaceOrientationMask = UIInterfaceOrientationMaskLandscapeRight;
//设置屏幕的转向为横屏
[[UIDevice currentDevice] setValue:@(UIDeviceOrientationLandscapeRight) forKey:@"orientation"];
}
else {
navigationController.interfaceOrientation = UIInterfaceOrientationPortrait;
navigationController.interfaceOrientationMask = UIInterfaceOrientationMaskPortrait;
//设置屏幕的转向为竖屏
[[UIDevice currentDevice] setValue:@(UIDeviceOrientationPortrait) forKey:@"orientation"];
}
//刷新
[UIViewController attemptRotationToDeviceOrientation];
}
- (BOOL)shouldAutorotate {
return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait ;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
@end
这个界面很简单,就一个按钮,每当点击的时候,设置一下RotateNavigationController的两个参数的值,并且切换一下屏幕的方向,同时,再刷新一下。这里的关键的方法是:
[[UIDevice currentDevice] setValue:@(UIDeviceOrientationLandscapeRight) forKey:@"orientation"];
这个方法能改变设备实际的旋转方向。
完成以上的几块内容,实际上就可以控制屏幕的横竖屏切换了。
本工程的例子已上传至github:IOS-Screenrotation-Control