- UINavigationController
- UiViewController1(锁定为竖屏)初始视图控制器,其上有一个按钮放置在导航栏上,用户可以通过该按钮访问列表,选择其他视图。
- UIViewController2(锁定为横屏)
- UiViewController3(支持竖屏和横屏)
- UiViewController4(支持竖屏和横屏)
- ...
- ...
根据 Swift Apple Docs 中有关 supportedInterfaceOrientations
的说明:
讨论
当用户更改设备方向时,系统会在填充窗口的根视图控制器或最上层的呈现视图控制器上调用此方法。如果视图控制器支持新方向,则窗口和视图控制器会旋转到新方向。仅当视图控制器的 shouldAutorotate 方法返回 true 时才会调用此方法。
您的导航控制器应该覆盖 shouldAutorotate
和 supportedInterfaceOrientations
,如下所示。我在一个 UINavigationController
扩展中完成了这个过程以便操作:
extension UINavigationController {
public override func shouldAutorotate() -> Bool {
return true
}
public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return (visibleViewController?.supportedInterfaceOrientations())!
}
}
你的主视图控制器(始终为纵向),应该具备:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
然后,在您希望支持纵向或横向的子视图控制器中:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.All
}
编辑:已更新至iOS 9 :-)
toRaw()
已被替换为rawValue
。 - ndbroadbent`override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}`
- charlieb这里还有一个[链接]提供了解答。
当你的视图层级比较复杂,例如有多个导航控制器和/或选项卡视图控制器时,情况可能会变得非常混乱。
这种实现方式是让各个视图控制器自行设置它们想要锁定方向的时间,而不是依赖于应用程序委托通过迭代子视图或依赖继承来查找它们。
Swift 3
在AppDelegate中:
/// set orientations you want to be allowed in this property by default
var orientationLock = UIInterfaceOrientationMask.all
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return self.orientationLock
}
struct AppUtility {
static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
if let delegate = UIApplication.shared.delegate as? AppDelegate {
delegate.orientationLock = orientation
}
}
/// OPTIONAL Added method to adjust lock and rotate to the desired orientation
static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
self.lockOrientation(orientation)
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
}
}
然后在您想要锁定方向的目标ViewController中:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
AppUtility.lockOrientation(.portrait)
// Or to rotate and lock
// AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Don't forget to reset when view is being removed
AppUtility.lockOrientation(.all)
}
如果您的视图在故事板中嵌入了导航控制器,请设置导航控制器代理 UINavigationControllerDelegate
并添加以下方法。
class ViewController: UIViewController, UINavigationControllerDelegate {
func navigationControllerSupportedInterfaceOrientations(navigationController: UINavigationController) -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
}
更新:如果在应用程序启动后设置方向时遇到问题,尝试使用ObjC
而不是Swift
,并使用class MyNavigationController: MyNavigationControllerBase
:
@implementation ABNavigationControllerBase
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
@end
Swift 3:
class MyNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
}
override var shouldAutorotate: Bool {
return false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}
}
在Swift 4.2+中回答与iOS 11兼容的相同问题(它可以正常工作)
1- 如下所示覆盖shouldAutorotate和supportedInterfaceOrientations。
extension UINavigationController {
open override var shouldAutorotate: Bool {
return true
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return (visibleViewController?.supportedInterfaceOrientations)!
}
}
2- 你的主视图控制器(始终为纵向),应该包含:
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.portrait
}
3- 在你想支持竖屏或横屏的子视图控制器中:
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.all
}
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask{
return UIInterfaceOrientationMask.portrait
}
很多人通过谷歌搜索来寻找这个答案,所以我希望你能原谅我。
适用于Swift 3.0
编辑为swift2.0:
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return [.Portrait, .PortraitUpsideDown]
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.orientation = UIInterfaceOrientationMaskPortrait;
//Or self.orientation = UIInterfaceOrientationPortraitUpsideDown
}
self.orientation = UIInterfaceOrientationLandscapeLeft:
self.orientation = UIInterfaceOrientationLandscapeRight:
或者您可以重写这个方法
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
这是我在iOS7中使用Obj-c实现的方法,我认为这段代码也适用于iOS8。
这里是Swift的更新内容:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
extension UINavigationController {
override open var shouldAutorotate: Bool {
return false
}
}
class ViewController: UIViewController {
/*
...
*/
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.portrait
}
}