旋转设备时约束不起作用

Posted

技术标签:

【中文标题】旋转设备时约束不起作用【英文标题】:Constraints not working when device is rotated 【发布时间】:2018-02-21 10:23:01 【问题描述】:

我有这个 UIViewController:

import UIKit

class ViewController: UIViewController 

    var object: DraggableView?

    override func viewDidLoad() 
        super.viewDidLoad() 
        // Create the object
        object = DraggableView(parent: self)
    

    override func viewWillAppear(_ animated: Bool) 
        super.viewWillAppear(animated)
        // Add subview
        object?.setup()
    

我有这个类可以在这个 VC 中添加视图:

import UIKit

class DraggableView 

    var parent: UIViewController!

    let pieceOfViewToShow: CGFloat = 30.0

    init(parent: UIViewController) 
        self.parent = parent
    

    func setup() 
        let view = UIView(frame: parent.view.frame)
        view.backgroundColor = UIColor.red
        parent.view.addSubview(view)
        view.translatesAutoresizingMaskIntoConstraints = false

        view.leadingAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.leadingAnchor).isActive = true
        view.trailingAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.trailingAnchor).isActive = true
        view.heightAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.heightAnchor).isActive = true

        // I need to show only a piece of the view at bottom, so:
        view.topAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.topAnchor, constant: parent.view.frame.height - pieceOfViewToShow).isActive = true
    

问题

一切都是正确的,但是当设备旋转时,它会失去约束,添加的视图也会丢失。

我认为问题在于下一行在设备旋转时无法更新正确的高度[parent.view.frame.height]

view.topAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.topAnchor, constant: parent.view.frame.height - pieceOfViewToShow).isActive = true

如何在旋转时更新这个常量? 我正在使用 Swift 3。

【问题讨论】:

【参考方案1】:

您可以尝试在UIView 上使用traitCollectionDidChange 回调来在旋转更改时更新约束,要使其正常工作,您需要将DraggableView 设为UIView 的子类:

import UIKit

class DraggableView: UIView 

    var parent: UIViewController!

    let pieceOfViewToShow: CGFloat = 30.0

    // keep the constraint around to have access to it
    var topConstraint: NSLayoutConstraint?

    init(parent: UIViewController) 
        super.init(frame: parent.view.frame)
        self.parent = parent
    

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

    func setup() 
        self.backgroundColor = UIColor.red
        parent.view.addSubview(self)
        self.translatesAutoresizingMaskIntoConstraints = false

        self.leadingAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.leadingAnchor).isActive = true
        self.trailingAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.trailingAnchor).isActive = true
        self.heightAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.heightAnchor).isActive = true

        // keep a reference to the constraint
        topConstraint = self.topAnchor.constraint(equalTo: parent.view.safeAreaLayoutGuide.topAnchor, constant: parent.view.frame.height - pieceOfViewToShow)
        topConstraint?.isActive = true
    

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) 
        super.traitCollectionDidChange(previousTraitCollection)

        // update the constraints constant
        topConstraint?.constant = parent.view.frame.height - pieceOfViewToShow
    

【讨论】:

@JaredPérez 抱歉,没有注意到 DraggableView 不是 UIView 的子类......只需使用更新版本 我认为这是一个不错的选择,但是在 DraggableView 类中你不能使用该方法:func traitCollectionDidChange

以上是关于旋转设备时约束不起作用的主要内容,如果未能解决你的问题,请参考以下文章

手机旋转后 LinearLayoutManager setOrientation 不起作用

UIButtons 在向右旋转时起作用,但在向左旋转时不起作用。嗯?

UIButtons 在某些设备上不起作用

为什么当旋转木马内部的某个元素被调用时,Bootstrap 4旋转木马暂停功能不起作用?

通过动画调整 UIView 大小时约束不起作用

日志,当屏幕旋转横向时方法不起作用