iOS ViewController 在方向更改后无法正确布局

Posted

技术标签:

【中文标题】iOS ViewController 在方向更改后无法正确布局【英文标题】:iOS ViewController doesn't layout properly after orientation change 【发布时间】:2015-09-16 14:39:18 【问题描述】:

我正在编写一个带有一些固定(纵向)视图和一些依赖于方向的视图(纵向、横向左侧和横向右侧)的 ios 应用程序。

视图包含在基于以下代码的自定义导航控制器中:

class CustomNavigationViewController: UINavigationController 
    override func supportedInterfaceOrientations() -> Int 
        return self.topViewController.supportedInterfaceOrientations()
    

    override func shouldAutorotate() -> Bool 
        return self.topViewController.shouldAutorotate()
    

我正在导航子控制器中实现supportedInterfaceOrientations()shouldAutorotate()

这是一个测试控制器

class TestViewController: UIViewController 
    var shouldRotate: Bool = false

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) 
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.shouldRotate = true
    

    required init(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
    

    convenience init(rotation shouldRotate: Bool) 
        self.init(nibName: "TestViewController", bundle: nil)
        self.shouldRotate = shouldRotate
    

    override func supportedInterfaceOrientations() -> Int 
        if shouldRotate == false 
            return UIInterfaceOrientation.Portrait.rawValue
         else 
            return super.supportedInterfaceOrientations()
        
    

    override func shouldAutorotate() -> Bool 
        return shouldRotate
    

    override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) 
        println("from: \(fromInterfaceOrientation.rawValue)")
    

    @IBAction func buttonTapped(sender: AnyObject) 
        let newvc = TestViewController(rotation: true)
        self.navigationController?.pushViewController(newvc, animated: true)
    

第一个控制器在AppDelegate 内部实例化为rotation: false。其他控制器使用rotation: true 创建并在点击按钮后推送。

这是视图的截图:

如果我在第一个控制器(可旋转控制器)之后改变控制器的方向,我会得到以下结果:

控制器 xib 使用自动布局,如果我在点击按钮之前旋转设备,它会按预期工作,视图会填满整个屏幕。

另外,如果我在手机处于横向状态时点击返回按钮,第一个视图将锁定在此状态:

我正在将应用程序部署到 iOS 8。

我怎样才能使第一个视图只显示纵向,而其他视图在旋转后正确布局?

【问题讨论】:

【参考方案1】:

这可能无关紧要,因为它只是打印出一条调试消息,但不要忘记 didRotateFromInterfaceOrientation(_:) 在 iOS 8 中已被贬低,viewWillTransitionToSize(_:withTransitionCoordinator:) 代替了视图大小更改的责任(其中包括旋转)。

我认为你在正确的轨道上,但不要同时覆盖 shouldAutorotate()supportedInterfaceOrientations() 只覆盖 supportedInterfaceOrientations()

我刚刚做了一个快速 POC,看看它是否可行。我在创建视图控制器(并使用 Swift 2)时没有设置标志,但你明白了:

class RotatingViewController: UIViewController 
    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask 
        return UIInterfaceOrientationMask.All
    


class FixedViewController: UIViewController 
    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask 
        return UIInterfaceOrientationMask.Portrait
    


class NavigationController: UINavigationController 
    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask 
        return self.topViewController?.supportedInterfaceOrientations() ?? UIInterfaceOrientationMask.All
    

我认为您的演示中发生的情况是,当您转换到固定的视图控制器时,您要求它进入纵向(它是)但不允许屏幕旋转回来到纵向模式。

所以.. 尝试删除 CustomNavigationViewController 中的“shouldAutorotate()”,看看是否可行。

【讨论】:

我已将测试项目更新为 swift 2 和 Xcode 7,然后将 shouldAutorotate() 更改为返回 true。现在它按预期工作。奇怪的是,我的项目中注释了正确的返回值,所以我确定我已经测试过这个解决方案,但由于某种原因没有奏效。谢谢。【参考方案2】:

问题是因为shouldAutorotate 返回false。 您的 FixedViewController 应该返回 shouldAutorotatetrue,但 supportedInterfaceOrientations 应该只是肖像。

你为什么需要它? 当您从另一个 RotateViewController 以横向模式返回(通过使用 popViewControllerdismissViewController)到您的 FixedViewController(仅支持纵向模式)时,它应该自动旋转,以返回纵向模式

【讨论】:

以上是关于iOS ViewController 在方向更改后无法正确布局的主要内容,如果未能解决你的问题,请参考以下文章

更改方向IOS后视图边界不更新

iOS:处理方向更改而不在视图控制器上启用横向模式

方向更改后iOS Maps UIPopover错位

IOS 6 方向 - 只有一个 Viewcontroller 支持横向和纵向方向 - 否则只支持纵向

在不继承 UINavigationController 的情况下以编程方式更改 ViewController 的方向

MKMapView 区域在 iOS7 中方向更改后损坏