1 首先在Xcode工程配置中设置 项目支持哪些方向上的旋转
从上往下分别是 上、下、左右 如图所示 表示当前项目 支持竖屏、左右横屏。Xcode中的配置是全局的,意味着项目中所有的控制器都默认支持这些方向的旋转。
2 控制器单独控制
Xcode工程配置中设置了全局支持的旋转方向,不过实际项目中经常不是所有的控制器都支持一样的旋转方向,所以需要通过代码实现控制器的单独配置。
为了能看懂代码 这里先介绍下跟旋转有关的三个枚举
UIDeviceOrientation: 设备旋转方向
typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom
UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top
UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right
UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left
UIDeviceOrientationFaceUp, // Device oriented flat, face up
UIDeviceOrientationFaceDown // Device oriented flat, face down
} API_UNAVAILABLE(tvos);
UIInterfaceOrientation:屏幕旋转方向
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
} API_UNAVAILABLE(tvos);
UIInterfaceOrientationMask:看代码的定义 可以理解为 用于对UIInterfaceOrientation的描述
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) {
UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
} API_UNAVAILABLE(tvos);
然后通过查看官方API可以看到UIViewController中声明了以下三个属性
// 是否支持屏幕旋转 当这个值为NO时 当前控制器只能竖屏
@property(nonatomic, readonly) BOOL shouldAutorotate ;
// 当前控制器支持的旋转方向
@property(nonatomic, readonly) UIInterfaceOrientationMask supportedInterfaceOrientations;
// 页面出现时的默认旋转方向
@property(nonatomic, readonly) UIInterfaceOrientation preferredInterfaceOrientationForPresentation;
这三个属性是只读的,所以没法用set方法去设置,不过可以通过重写get方法的形势来返回想要的值 比如以下代码所示
// 返回yes表示支持旋转
- (BOOL)shouldAutorotate
{
return YES;
}
// 支持竖屏和横屏
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape);
}
// 默认旋转左边
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
不过要注意的是 如果当前控制器是属于一个导航控制器的 那么导航控制器中要实现
// 是否支持自动转屏
- (BOOL)shouldAutorotate {
return self.topViewController.shouldAutorotate;
}
// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return self.topViewController.supportedInterfaceOrientations;
}
// 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.topViewController.preferredInterfaceOrientationForPresentation;
}
同样的 如果控制器外面还有一层TabBarViewControllre那么 TabBarViewControllre要实现
// 是否支持自动转屏
- (BOOL)shouldAutorotate {
return self.selectedViewController.shouldAutorotate;
}
// 支持哪些屏幕方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return self.selectedViewController.supportedInterfaceOrientations;
}
// 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.selectedViewController.preferredInterfaceOrientationForPresentation;
}
到了这里 我们就知道了 怎么全局或单独配置某个ViewController是否支持、支持哪些方向的旋转。当手机设备旋转时,界面也会相应的旋转。
3 监听屏幕的旋转
既然某个VC支持了屏幕旋转,也就意味着 该界面的竖屏和横屏是两套不同的UI,所以当屏幕旋转时,监听系统发出的通知,及时刷新UI 做好横竖屏的适配。
// 监听屏幕旋转
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil];
- (void)orientationDidChange
{
switch ([UIDevice currentDevice].orientation) {
case UIDeviceOrientationPortrait:
self.isFullScreen = NO;
break;
case UIDeviceOrientationLandscapeLeft:
self.isFullScreen = YES;
break;
case UIDeviceOrientationLandscapeRight:
self.isFullScreen = YES;
break;
default:
break;
}
}
4 主动控制屏幕的旋转
当锁定了iPhone的方向之后,旋转手机,UIDevice的orientation属性不会改变,同时系统也不会发出UIDeviceOrientationDidChangeNotification通知,此时我们只能通过代码的方式强制修改当前Device的orientation,当orientation改变时,系统会发出UIDeviceOrientationDidChangeNotification通知
// 因为orientation属性是只读的 所有这里通过KVC的形式来设置值
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:orientation]
forKey:@"orientation"];