1. 屏幕旋转相关知识
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
} __TVOS_PROHIBITED;
UIInterfaceOrientation: 界面方向
// Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
// This is because rotating the device to the left requires rotating the content to the right.
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
} __TVOS_PROHIBITED;
UIInterfaceOrientationMask: 是用来控制允许转向的方向
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),
} __TVOS_PROHIBITED;
2. 观察屏幕旋转
if (![UIDevice currentDevice].isGeneratingDeviceOrientationNotifications) {
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}
// 锁定竖屏仍然有效
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
// Handle device orientation changes
- (void)deviceOrientationDidChange: (NSNotification *)notification
{
// If dialog is attached to the parent view, it probably wants to handle the orientation change itself
if (parentView != NULL) {
return;
}
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
[self changeOrientationForIOS7];
} else {
[self changeOrientationForIOS8:notification];
}
}
// Rotation changed, on iOS8
- (void)changeOrientationForIOS8: (NSNotification *)notification {
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
[UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone
animations:^{
CGSize dialogSize = [self countDialogSize];
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
self.frame = CGRectMake(0, 0, screenWidth, screenHeight);
dialogView.frame = CGRectMake((screenWidth - dialogSize.width) / 2, (screenHeight - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height);
}
completion:nil
];
}
- (void)dealloc
{
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
- (void)statusBarOrientationChange:(NSNotification *)noti{
[self resetBGView];
[self updateMainView];
[self updateChatListView];
[self updateCircleListView];
[self updateShareCircleDetailView];
}
- 监听设备方向,会返回多个方向,不冲突。
- 监听设备方向,先是设备旋转,然后才是界面旋转,在操作界面时,可能界面还没有旋转。
3. 控制屏幕旋转的函数
// 是否支持旋转
- (BOOL)shouldAutorotate {
return YES;
}
// 支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
// 模态时默认方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
4. 不同根控制器情况下的解决
- UIViewController根控制器
// 是否支持旋转
- (BOOL)shouldAutorotate {
return NO;
}
// 支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
// 默认方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
- UINavigationController根控制器
// 是否支持旋转
- (BOOL)shouldAutorotate {
return self.viewControllers.lastObject.shouldAutorotate ? YES : NO;
}
// 支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return self.viewControllers.lastObject.supportedInterfaceOrientations ? self.viewControllers.lastObject.supportedInterfaceOrientations : UIInterfaceOrientationMaskPortrait;
}
// 默认方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.viewControllers.lastObject.preferredInterfaceOrientationForPresentation ? self.viewControllers.lastObject.preferredInterfaceOrientationForPresentation : UIInterfaceOrientationPortrait;
}
- UITabBarController根控制器
// 是否支持旋转
- (BOOL)shouldAutorotate {
return self.selectedViewController.shouldAutorotate ? YES : NO;
}
// 支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return self.selectedViewController.supportedInterfaceOrientations ? self.selectedViewController.supportedInterfaceOrientations : UIInterfaceOrientationMaskPortrait;
}
// 默认方向
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.selectedViewController.preferredInterfaceOrientationForPresentation ? self.selectedViewController.preferredInterfaceOrientationForPresentation : UIInterfaceOrientationPortrait;
}
- 更简单的实现方案 来个Swift版本的
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?)
-> UIInterfaceOrientationMask {
}
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?)
-> UIInterfaceOrientationMask {
if isAllowAutorotate {
return [.portrait, .landscapeLeft, .landscapeRight]
}
else {
return .portrait
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
isAllowAutorotate = false
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
isAllowAutorotate = true
}
}
横屏跳竖屏 竖屏跳横屏
- Present情况
override var preferredInterfaceOrientationForPresentation:
UIInterfaceOrientation {
return .portrait
}
- Push情况
override var shouldAutorotate: Bool {
return true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// 切换到你想要的方向
driveScreen(to: .portrait)
}
func driveScreen(to direction: UIInterfaceOrientation) {
UIDevice.current.setValue(direction.rawValue, forKey: "orientation")
}
补充:iOS 获取屏幕方向
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
}else {
}
不推荐使用UIDevice来获取屏幕方向,因为第一次获取的时候会获得UIDeviceOrientationUnknown UIDeviceOrientation duration = [[UIDevice currentDevice] orientation];
强制屏幕旋转
- (void)interfaceOrientation:(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];
}
}