Recalculate SnapKit Constraint on orientation change

1.9k views Asked by At

I want to recalculate the height constraint when the phone orientation changes. I'm using the functions uninstall() and install() to make this happen. However, it's not working as desired. Am I using them incorrectly?

class ActionOverlayViewController: UIViewController {
    private var tableView = UITableView()
    private var heightConstraint: Constraint?

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.snp_makeConstraints { make in
            self.heightConstraint = make.height.lessThanOrEqualTo(UIScreen.mainScreen().bounds.size.height).priorityHigh().constraint
            make.height.equalTo(242).priorityLow()
        }
    }

    override func updateViewConstraints() {
        tableView.snp_updateConstraints { make in
            self.heightConstraint.uninstall()
            self.heightConstraint.install()
        }
        super.updateViewConstraints()
    }

    override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        updateViewConstraints()
    }
}
1

There are 1 answers

0
joern On

If you want to have your tableView to have different heights in Landscape and Portrait orientation you could use 2 different approaches:

1. Height should be 200 in Landscape and 400 in Portrait:

class ViewController: UIViewController {

    let tableView = UITableView()
    var heightConstraint: Constraint?

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(tableView)

        tableView.snp.makeConstraints { (make) in
            make.top.left.right.equalTo(0)
            self.heightConstraint = make.height.equalTo(0).constraint
        }
    }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        let height = UIDevice.current.orientation.isLandscape ? 200 : 400
        heightConstraint?.update(offset: height)
    }
}

Here you only have to call update(offset:) on the constraint. No need to go through updateViewConstraints(). This works well if you have static heights.

2. Height should be half of the screen height in Portrait and full screen in Landscape:

Here you have to update the whole constraints because you don't use static heights. Because of that you do not need to keep a reference to the constraint, but you have to go through updateViewConstraint():

class ViewController: UIViewController {

    let tableView = UITableView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(tableView)
    }

    override func updateViewConstraints() {
        super.updateViewConstraints()
        tableView.snp.remakeConstraints { (make) in
            make.top.left.right.equalTo(0)
            if UIDevice.current.orientation.isLandscape {
                make.bottom.equalTo(0)
            } else {
                make.bottom.equalTo(view.snp.centerY)
            }
        }
    }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        view.setNeedsUpdateConstraints()
    }
}