safeAreaLayoutGuide - ландшафтный режим

Я установил safeAreaLayoutGuide следующим образом:

let guide = view.safeAreaLayoutGuide

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

это прекрасно работает Однако, когда я поворачиваю устройство в альбомный режим, строка состояния (батарея, сигнал и т. Д.) Отсутствует, и смещение от верхней части экрана равно нулю. Это правильно, на основе якоря. Тем не менее, это не выглядит хорошо. Как добавить смещение 20 для ландшафта при создании якорей? Я не хочу менять константу в зависимости от ориентации вручную.

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)

метод и поменяйте местами активное состояние двух ограничений на основе нового класса ориентации / размера.

Следует отметить, что сначала необходимо всегда деактивировать ограничения, а затем активировать их, чтобы избежать каких-либо жалоб на ограничения, которые не могут быть выполнены.

Другие вопросы по тегам