如何在 Swift 中设备方向发生变化时更新 UI?

How to update the UI when the device orientation changed in Swift?

我正在寻找如何在设备方向发生变化时更新 UIs,但我现在卡住了,需要一些帮助。

我用 Swift 制作了一个登录屏幕,并以编程方式创建了它的 UI。 对于 info.plist 中支持的方向,我设置

这是登录屏幕。

当我使用 Portrait 构建和 运行 时,它工作正常,但是当我旋转设备时,UI 变成这样。

好像设备方向改为横向,但UI仍然是纵向,所以屏幕右侧变黑了。

这是视图文件(我没有放完整的代码),我有一个包含其他 UI 的堆栈视图。

class LoginView: UIView {
    lazy private var stackView = UIStackView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupStackView()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    private func setupStackView() {
        stackView.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(stackView)
        stackView.axis = .vertical
        stackView.alignment = .fill
        stackView.spacing = 20
        stackView.distribution = .fill
    
        stackView.addArrangedSubview(titleText)
        stackView.addArrangedSubview(greenView)

    
        NSLayoutConstraint.activate([
            stackView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.9),
            stackView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
            stackView.centerYAnchor.constraint(equalTo: self.centerYAnchor)
        ])
    }

视图控制器是这样的。

class LoginViewController: UIViewController {

    private let loginView = LoginView()

    override func viewDidLoad() {
    
        view.addSubview(loginView)
        loginView.frame = CGRect(origin: .zero, size: view.bounds.size)
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        print("the view is rotated")
    }
}

我收到消息“视图已旋转”,旋转部分似乎没有问题,但无法将视图控制器本身更新为水平并更新 UIs。

我想知道为什么我的视图控制器在设备处于横向模式时保持垂直,以及如何更新它。

请问谁能指引我正确的方向吗?

实际使用

loginView.frame = CGRect(origin: .zero, size: view.bounds.size)

您为登录视图分配了一个框架,该框架不会随设备旋转而改变。

您可能还想在这里使用约束方法:

// try replacing
// loginView.frame = CGRect(origin: .zero, size: view.bounds.size)

// with
 loginView.translatesAutoresizingMaskIntoConstraints = false
 NSLayoutConstraint.activate([
    loginView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    loginView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    loginView.topAnchor.constraint(equalTo: view.topAnchor),
    loginView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
 ])

另一种方法是更新登录视图的框架,例如

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
   super.traitCollectionDidChange(previousTraitCollection)
   loginView.frame = CGRect(origin: .zero, size: view.bounds.size)
}

最后但同样重要的是,您可以在 viewDidLoad

中使用 autoresizingMask
loginView.frame = CGRect(origin: .zero, size: view.bounds.size)
loginView.autoresizingMask = [.flexibleHeight, .flexibleWidth]

P.S。我之前的评论具有误导性,因为登录框架未在 setupStackView() 函数中设置

最后的评论:

// you can replace
loginView.frame = CGRect(origin: .zero, size: view.bounds.size)
// with
loginView.frame = view.bounds