Is it possible to change the constraints when the device is rotated? How might this be achieved?
A simple example might be two images which, in portrait, are stacked one above the other, but in landscape are side-by-side.
If this is not possible, how else might I accomplish this layout?
I am constructing my views and constraints in code and not using interface builder.
The approach I am using (for better or worse) is to define both sets of constraints (portrait and landscape) in the storyboard editor.
To avoid the storyboard warnings of hell, I place all of one set at a priority of 999, just so it doesn't show red everywhere.
Then I add all of the constraints to outlet collections:
Finally, I implement my
ViewControllers
'sviewWillLayout
method:This seems to work. I really wish you could set the default active property in the the storyboard editor.
My idea is to handle orientation by changing constraint priorities.
Supposing priorities will be:
Step 1: Create landscape (or portrait) design in Storyboard with constraints.
Step 2: For constraints, that must be active only for landscape mode set priority to 10.
Step 3: Add constraints for portrait mode and set their priority to 920.
In
willAnimateRotationToInterfaceOrientation
add code:Advantage of this approach - easy adjusting in Interface Builder. When we need to switch to any orientation, we select all constraints by priority and change them simultaneously (910->10, 20->920):
Interface will rebuilded automatically.
You can save your constraints, to a property or variable as portrait and landscape versions then set and remove them on rotate.
I have done this making my constraints in xib for initial view, assigning them to outlets in the view controller. On rotate I create the alternate restraints, remove the outlets but retain them, insert the alternates.
Reverse the process on rotate back.
Edit: Using the new concept of Size Classes introduced in Xcode 6, you can easily setup different constraints for specific size classes in Interface Builder. Most devices (e.g. all current iPhones) have a Compact vertical size class in landscape mode.
This is a much better concept for general layout decisions than determining the device's orientation.
That being said, if you really need to know the orientation,
UIDevice.currentDevice().orientation
is the way to go.Original post:
Override the
updateViewConstraints
method ofUIViewController
to provide layout constraints for specific situations. This way, the layout is always set up the correct way according to situation. Make sure they form a complete set of constraints with those created within the storyboard. You can use IB to set up your general constraints and mark those subject to change to be removed at runtime.I use the following implementation to present a different set of constraints for each orientation:
Now, all you need to do is trigger a constraint update whenever the situation changes. Override
willAnimateRotationToInterfaceOrientation:duration:
to animate the constraint update on orientation change:I am following the same approach as yours (no nib files or storyboards). You have to update your constraints in
updateViewConstraints
method (by checking the device orientation). There is no need to callsetNeedsUpdateConstraints
inupdateViewConstraints
because as soon as you change the device orientation the last method is called automatically.