famer
famer

Reputation: 499

Xcode autolayout: keep minimum between height and width of square

I used fixed aspect ratio for UIView so it's square. Then I set fixed trailing and leading space to borders of the screen they are the same. And kept vertical centered position. So in result I've got square on the center of the screen with some equal space before and after, if screen is wider square is bigger. That works perfectly in portrait orientation. But when I use landscape orientation, size of the square based on leading and trailing space becomes bigger than height of the device so it's not fit. Is it a way to have square based on constrains and choosing smallest of two dimensions? Is it a way to have spacing to the screen borders different for iPhone and iPad?

Upvotes: 4

Views: 7609

Answers (4)

Heath Borders
Heath Borders

Reputation: 32107

I got this working with:

NSLayoutConstraint.activate([
  self.subview.widthAnchor.constraint(equalTo: self.subview.heightAnchor),
  self.subview.layoutMarginsGuide.centerXAnchor.constraint(equalTo: self.superview.centerXAnchor),
  self.subview.layoutMarginsGuide.centerYAnchor.constraint(equalTo: self.superview.centerYAnchor),
  self.subview.widthAnchor.constraint(lessThanOrEqualTo: self.superview.widthAnchor),
  self.subview.heightAnchor.constraint(lessThanOrEqualTo: self.superview.heightAnchor),
])
        
// this can be either width or height since width = height above
let lowPriorityWidthConstraint = self.subview.widthAnchor.constraint(equalTo:self.superview.widthAnchor)
lowPriorityWidthConstraint.priority = .defaultHigh
lowPriorityWidthConstraint.isActive = true

// defining this doesn't hurt, but is superfluous
let lowPriorityHeightConstraint = self.subview.heightAnchor.constraint(equalTo:self.superview.heightAnchor)
lowPriorityHeightConstraint.priority = .defaultHigh
lowPriorityHeightConstraint.isActive = true

Upvotes: 0

rockdaswift
rockdaswift

Reputation: 9983

Add two constraints for center vertically and horizontally the view.

Add two constraints for the width:

  • Width equal to the superview (priority 750)
  • Width less than or equal to the superview (priority 750)

Add constraint with the Height less than or equal to the superview (priority 1000).

Another constraint with aspect ratio 1:1.

Upvotes: 1

Ken Thomases
Ken Thomases

Reputation: 90521

Add an inequality constraint for the Top such that the spacing is greater than or equal to your minimum.

That will actually create a conflict with your other constraints. You can resolve that by lowering the priority of the Leading and Trailing constraints. Unfortunately, that leaves ambiguity. When the superview is wider than the square, should the Leading constraint or the Trailing constraint hold?

Actually, you don't want either to hold. That would put the square off to one side or the other. You want the square centered. So, remove the Trailing constraint and instead add a constraint to keep the square centered in its superview.

So, in summary:

  • Two constraints, vertical and horizontal, to keep the square centered.
  • A Top constraint to keep the space there greater than or equal to the minimum.
  • A Leading constraint to keep the space there equal to the minimum but lower its priority.

When the superview is narrower than it is tall, the Top constraint will be easily satisfied (the space will be greater than the minimum). So, the Leading constraint will govern the size of the square.

When the superview is wider than it is tall, the Leading constraint will try to make the square so big that its top and bottom go out of its superview. However, the Top constraint will prevent that from happening. The system will allow the Leading constraint to be broken because it's lower priority, but it will still try to get as close as possible to satisfying it. That will make sure the square is as big as will fit.

Upvotes: 6

jday
jday

Reputation: 578

Check out size classes in your storyboard: https://developer.apple.com/library/ios/recipes/xcode_help-IB_adaptive_sizes/chapters/AboutAdaptiveSizeDesign.html

When your constraint is selected, you can click the little + next to Constant and then choose a size class to have a separate constraint. If you are working with iPhones in landscape, check out Any Width x Compact Height:

screenshot

A cool way to see these in action is to show the assistant editor (middle interlocking rings icon). From the menu at the top of the view that appears, select Preview and the name of your storyboard. Then you have the ability to add previews for different devices and see how your constraints will show up on each. You can also rotate those previews back and forth between portrait and landscape. It's a really helpful tool for knowing when your constraints are set properly.

Upvotes: 0

Related Questions