一: 序
二: 基本知识点了解
三: 屏幕旋转流程
四: 屏幕旋转设置
四: 结言
序:
这几天项目要适配ipad,适配倒是没出啥问题,没想到横竖屏幕切换出了问题,只好再看看查查看喽@@好吧还是记录一下吧,省的以后又忘了!
二: 基本知识点了解
2.1屏幕旋转 orientation 分为两种
1、device orientation
设备的物理方向
2、interface orientation
界面显示的方向
三: 屏幕旋转流程
加速计是整个IOS屏幕旋转的基础。
依赖加速计,设备才可以判断出当前的设备方向。
当加速计检测到方向变化的时候,会发出
UIDeviceOrientationDidChangeNotification 通知。
屏幕旋转的流程如下:
1、加速计来识别设备的旋转方向。
发送 UIDeviceOrientationDidChangeNotification 设备旋转的通知。
2、app 接收到旋转事件(通知事件)。
2、app 通过AppDelegate通知当前程序的KeyWindow。
3、Window 会知会它的 rootViewController,判断该view controller所支持的旋转方向,完成旋转。
4、如果存在 modal 的view controller的话,系统则会根据 modal 的view controller,来判断是否要进行旋转。
四: 屏幕旋转设置
4.1、如果项目整体不需要旋转,可以如下设置(不推荐)
4.2、如果项目需要个别页面进行横竖屏切换,那就需要代码控制
4.2.1、 api接口使用
//是否支持屏幕旋转 (返回 NO 后面俩方法不调用,后面只支持竖直方向)
override var shouldAutorotate: Bool {
return true
}
//支持屏幕旋转的方向
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscapeLeft
}
//返回现在正在显示的用户界面方向
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .landscapeLeft
}
4.2.1.1、 supportedInterfaceOrientations 使用说明:
此方法返回当前viewController 支持的方向. 但是, 只有两种情况下此方法才会生效:
1、当前viewController是window的rootViewController.
2、当前viewController是modal模式的. 即, 此viewController是被调用
presentModalViewController 而显示出来的.
在以上两种情况中,UIViewController.supportedInterfaceOrientations 方法会作用于前viewController和所有childViewController. 以上两种情况之外, UIKit并不会理会你的supportedInterfaceOrientations 方法.
如果某个viewController实现了以上方法. 则, 此viewController就支持竖方向和左旋转方向. 此viewController的所有childViewController也同时支持这两个方向, 不多不少.
4.2.1.2、 preferredInterfaceOrientationForPresentation 使用说明:
此方法也仅有在当前viewController是rootViewController或者是modal模式时才生效.
4.2.1.3、 shouldAutorotate 使用说明:
用于设置当前viewController是否支持自动旋转. 如果,你需要viewController
暂停自动旋转一小会儿. 那么可以通过这个方法来实现.
同样的, 此方法也仅有在当前viewController是rootViewController或者是modal模式时才生效.
4.2.1.4、 代码设置:
由于全局性考虑,我们在此设置UINavigationController UITabBarController 和 所有视图控制器的父类BaseUIViewController,这三个类根据自己需求进行自定义,如果不需要可以不设置, 同时在AppDelegate中也需要设置.
UINavigationController
在此类中加入如下代码:
private extension UINavigationController {
var _visibleViewController: UIViewController? {
guard let viewController = self.topViewController else { return nil }
if let nc = viewController as? UINavigationController, let topViewController = nc.topViewController {
return topViewController
} else {
return viewController
}
}
}
override var shouldAutorotate: Bool {
return self._visibleViewController?.shouldAutorotate ?? false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return self._visibleViewController?.supportedInterfaceOrientations ?? .portrait
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return self._visibleViewController?.preferredInterfaceOrientationForPresentation ?? .portrait
}
UITabBarController
在此类中加入如下代码:
private extension UITabBarController {
var _visibleViewController: UIViewController? {
guard let viewController = self.selectedViewController else { return nil }
if let nc = viewController as? UINavigationController, let topViewController = nc.topViewController {
return topViewController
} else {
return viewController
}
}
}
override var shouldAutorotate: Bool {
return self._visibleViewController?.shouldAutorotate ?? false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return self._visibleViewController?.supportedInterfaceOrientations ?? .portrait
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return self._visibleViewController?.preferredInterfaceOrientationForPresentation ?? .portrait
}
UIViewController
在此类中加入如下代码:
override var shouldAutorotate: Bool {
return false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}
AppDelegate(必须设置)
在此类中加入如下代码:
var blockRotation: Bool = false
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return blockRotation ? .all : .portrait
}
如果项目只需要横屏或竖屏那么只需要在上面的类中直接设置死就可以了.
如果项目想某个页面需要横屏或竖屏请进行如下操作:
在需要旋转的页面设置
let appDelegate = UIApplication.shared.delegate as! AppDelegate
override func viewDidLoad() {
appDelegate.blockRotation = true
}
override func viewWillAppear(_ animated: Bool) {
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
appDelegate.blockRotation = false
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscapeLeft
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .landscapeLeft
}
四: 结言
以上内容有很多不完整或错误的地方,还望指正,在此也只是略做说明.