问题
iOS开发中大部分情况都是只允许竖屏的,但是偶尔几个页面需要做横屏处理(或者只能横屏)
解决方案
Applegate.swift文件中的修改
首先在AppDelegate中新增属性
var isLandscape = false
然后给AppDelegate新增扩展
// MARK: - 是否横屏
extension AppDelegate {
@objc(application:supportedInterfaceOrientationsForWindow:) func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if isLandscape {
//return .landscapeRight //只允许全景模式(横屏)
return .all //允许所有模式,手机转动会跟随转动
}else{
return .portrait //只能竖屏
}
}
}
/***
解决iOS 9 横竖屏的问题
This is a bug in iOS 9 that it failed to retrieve the supportedInterfaceOrientations for UIAlertController. And it seems it dropped to an infinite recursion loop in looking for the supportedInterfaceOrientations for UIAlertController
https://stackoverflow.com/questions/31406820/uialertcontrollersupportedinterfaceorientations-was-invoked-recursively
*/
extension UIAlertController {
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.portrait
}
open override var shouldAutorotate: Bool {
return false
}
}
在 info.plist
添加
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
设置好了后,接下来处理需要横屏幕的页面
需要横屏的页面BTKLineVC
// MARK: - 横屏处理
extension BTKLineVC {
//运行页面随设备转动
override var shouldAutorotate : Bool {
return true
}
override func viewWillAppear(_ animated: Bool) {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
//允许横屏
appDelegate.isLandscape = true
// 强制横屏打开下面两行代码即可
//let value = UIInterfaceOrientation.landscapeRight.rawValue
//UIDevice.current.setValue(value, forKey: "orientation")
}
super.viewWillAppear(animated)
}
override func viewWillDisappear(_ animated: Bool) {
navigationController?.setNavigationBarHidden(false, animated: false)
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
//禁止横屏
appDelegate.isLandscape = false
}
//强制为竖屏
let value = UIInterfaceOrientation.portrait.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
super.viewWillDisappear(animated)
}
//下面方法是处理navgation相关的逻辑,如果控制器没有nav,省略
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: { [weak self] (context) in
let orient = UIApplication.shared.statusBarOrientation
switch orient {
case .landscapeLeft, .landscapeRight:
//横屏时禁止左拽滑出
self?.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
self?.navigationController?.setNavigationBarHidden(true, animated: false)
default:
//竖屏时允许左拽滑出
self?.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
self?.navigationController?.setNavigationBarHidden(false, animated: false)
}
})
super.viewWillTransition(to: size, with: coordinator)
}
}
8月3号 补充
上面处理横屏会引起一个bug,就是如果手机横屏进入(与设置方向相同),布局可能会错乱。
原因是:这里布局我是按照横屏处理的,以上处理横屏方式适用于页面跟随系统,即页面可以横屏也可以竖屏
bug解决办法
-
设置系统只能竖屏
需要横屏的页面取消方向跟随系统,只允许横屏
// MARK: - 横屏处理
extension BTKLineVC {
//运行页面随设备转动
override open var shouldAutorotate: Bool {
return false
}
//支持的方向: 右边
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscapeRight
}
// 优先展示的方向: 右边
override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .landscapeRight
}
}
11月25号更新
在iOS13时,对于 present 的页面,需要设置取消弹框新模式 添加以下代码在viewDidLoad中即可:
modalPresentationStyle = UIModalPresentationStyle.fullScreen
备注
本文swift版本用的是swift4,如果代码异常根据版本稍作修改即可食用, 用OC的同学可以根据代码自行翻译,早用swift,脱离OC苦海。