safeAreaLayoutGuide - 横向模式

时间:2018-01-01 11:33:21

标签: ios swift autolayout safearealayoutguide

我已经设置了safeAreaLayoutGuide:

let guide = view.safeAreaLayoutGuide

NSLayoutConstraint.activate([
  topControls.topAnchor.constraint(equalTo: guide.topAnchor, constant: 0)
])

这很有效。但是,当我将设备旋转到横向模式时,没有状态栏(电池,信号等),并且屏幕顶部的偏移为零。这是正确的,基于锚。但是,它看起来不太好。如何在锚点创建过程中为横向添加偏移量20?我不想手动改变基于方向的常数。

1 个答案:

答案 0 :(得分:1)

假设您在iPhone上运行,那么这是预期的行为,可以通过覆盖以下内容来更改:

override var prefersStatusBarHidden: Bool {
    return false
}

从该UIViewController方法的描述:

  

默认情况下,此方法返回false,但有一个例外。对于应用程序   链接到iOS 8或更高版本,如果视图,此方法返回true   控制器处于垂直紧凑的环境中。

如果您覆盖它,那么您将获得横向状态栏,安全区域指南将相应地进行调整。

修改

因此对原始要求略有误解。它不是显示状态栏,而是存在差距,就像有状态栏一样。

这需要手动完成,因为您无法设置仅适用于某些方向/大小类的约束。

这是一个基本的UIViewController,可以满足您的需求:

class ViewController: UIViewController {
    var testView: UIView!
    var landscapeConstraint: NSLayoutConstraint!
    var portraitConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.testView = UIView()
        self.testView.backgroundColor = .green
        self.view.addSubview(self.testView)
        self.testView.translatesAutoresizingMaskIntoConstraints = false

        let guide = view.safeAreaLayoutGuide

        self.testView.leftAnchor.constraint(equalTo: guide.leftAnchor, constant: 0).isActive = true
        self.testView.rightAnchor.constraint(equalTo: guide.rightAnchor, constant: 0).isActive = true
        self.testView.bottomAnchor.constraint(equalTo: guide.bottomAnchor, constant: 0).isActive = true

        self.portraitConstraint = self.testView.topAnchor.constraint(equalTo: guide.topAnchor, constant: 0)
        self.landscapeConstraint = self.testView.topAnchor.constraint(equalTo: guide.topAnchor, constant: 20) // Hardcoded the size but this can be anything you want.

        switch self.traitCollection.verticalSizeClass {
        case .compact:
            self.landscapeConstraint.isActive = true
        case.regular:
            self.portraitConstraint.isActive = true
        default: // This shouldn't happen but let's assume regular (i.e. portrait)
            self.portraitConstraint.isActive = true
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
        super.willTransition(to: newCollection, with: coordinator)

        switch newCollection.verticalSizeClass {
        case .compact:
            self.portraitConstraint.isActive = false
            self.landscapeConstraint.isActive = true
        case.regular:
            self.landscapeConstraint.isActive = false
            self.portraitConstraint.isActive = true
        default: // This shouldn't happen but let's assume regular (i.e. portrait)
            self.landscapeConstraint.isActive = false
            self.portraitConstraint.isActive = true
        }
    }
}

基本上,您设置固定约束,即左,右和底,然后设置纵向和横向(常规和紧凑垂直尺寸类)的约束,默认情况下均禁用。 然后根据当前方向/大小类决定激活哪一个。 然后你覆盖:

willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)

方法并根据新的方向/大小类交换两个约束的活动状态。

需要注意的一件事是始终首先停用约束,然后激活约束以避免任何抱怨无法满足的约束。