Autolayout to size views on different devices

Recently I ran into a not so interesting auto layout problem. I wanted to show a view which would stretch to the full width of iPhone with fixed padding like this

view_on_iPhone

However, I also wanted to display the same view on iPad. But not stretching to the full device width. If it's an iPad device, I wanted to constrain its width to fixed size so as not to make it look ugly like this

Actual:
actual_view_on_iPad

Of course I would've added an if-else statement to check if device was iPad or iPhone. But in my opinion that was an ugly hack rather than having to use power of NSLayoutConstraint and priority associated with them.

In order to make the view work on both devices without need of if-else, I added two constraint with varied priority.

  • First one was to stretch the view to superview's full width with fixed padding of 20px on both sides. This was assigned a low priority of 999 units

let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .red
self.view.addSubview(view)
let views = ["view": view]
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-100-[view(44)]", options: [], metrics: nil, views: views))
self.view.addConstraint(NSLayoutConstraint(item: view, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 0))

// First horizontal constraint with low priority
let minorWidthConstraint = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: self.view.frame.width - 40)
minorWidthConstraint.priority = 999
self.view.addConstraint(minorWidthConstraint)
  • Second one was to limit the maximum width of view to 400px on any device. This constraint was setup with required priority of 1000 units

let majorWidthConstraint = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .lessThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 400)
majorWidthConstraint.priority = 1000
self.view.addConstraint(majorWidthConstraint)

Just as I expected, when the view was being displayed on iPad, second constraint with higher priority kicked in and limit the maximum width of view to 400px preventing it from extending near the edges.

Result on iPad was with view constrained to its maximum width as follows.

expected_view_iPad

Hope this small trick will help you anytime with auto layout adventures.

If you have any questions/queries/concerns, do not hesitate to write in comment section. You can also message me directly on the Twitter