0
votes

I want to set a subview constraint as follows. If the interface is landscape (view.bounds.width > view.bounds.height),set aspect ratio of subview to be 4:3. In portrait mode, it should be 3:4. While I can always change the constraints programmatically on auto rotation, wondering if there is a clever way of designing constraints that is only one time.

1
On a phone you can use size classes and link constraints to those size classes. Unfortunately the iPad has the same size classes in both portrait and landscape so you will need some code to override the traits based on the orientation.Paulw11

1 Answers

1
votes

You'll have to listen for the UIDevice.orientationDidChangeNotification notification like in this example:

class ViewController3: UIViewController {

    let blueSubview: UIView = {
        let view = UIView()
        view.backgroundColor = .blue
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    var blueSubviewHeight = NSLayoutConstraint()
    var blueSubviewWidth = NSLayoutConstraint()

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(refreshConstraints), name: UIDevice.orientationDidChangeNotification, object: nil)

        refreshConstraints()
        setUI()
    }

    fileprivate func setUI() {
        view.backgroundColor = .white

        view.addSubview(blueSubview)
        [blueSubview.leftAnchor.constraint(equalTo: view.leftAnchor),
        blueSubview.topAnchor.constraint(equalTo: view.topAnchor),
        blueSubviewWidth,
        blueSubviewHeight].forEach({ $0.isActive = true })
    }

    @objc func refreshConstraints() {
        NSLayoutConstraint.deactivate([blueSubviewWidth, blueSubviewHeight])

        if view.frame.width > view.frame.height {
            blueSubviewWidth = blueSubview.widthAnchor.constraint(equalToConstant: view.frame.height * (4/3))
            blueSubviewHeight = blueSubview.heightAnchor.constraint(equalToConstant: view.frame.height)
        }
        else {
            blueSubviewWidth = blueSubview.widthAnchor.constraint(equalToConstant: view.frame.width)
            blueSubviewHeight = blueSubview.heightAnchor.constraint(equalToConstant: view.frame.width * (4/3))
        }

        NSLayoutConstraint.activate([blueSubviewWidth, blueSubviewHeight])
    }
}