Can I use autostart to provide various restrictions for landscape and portrait orientation?

Can I change the restrictions when turning the device? How can this be achieved?

A simple example would be two images, which in the portrait are stacked one above the other, but in the landscape side by side.

If this is not possible, how else can I execute this layout?

I create my representations and restrictions in the code and do not use the interface constructor.

+46
ios cocoa-touch autolayout uiviewcontroller uiview
Jul 21 '13 at 13:40
source share
5 answers

Edit: Using the new dimension class concept introduced in Xcode 6, you can easily configure various restrictions for specific size classes in Interface Builder. Most devices (such as all current iPhones) have a compact vertical dimension class in landscape mode.

This is a much better concept for general layout decisions than determining device orientation.

However, if you really need to know the orientation, UIDevice.currentDevice().orientation is the way to go.




Original post:

Override the updateViewConstraints method of the updateViewConstraints to provide layout constraints for specific situations. Thus, the layout is always customized according to the situation. Make sure they form a complete set of constraints with those created in the storyboard. You can use IB to configure your general restrictions and mark those who will be changed to be deleted at runtime.

I use the following implementation to represent a different set of constraints for each orientation:

 -(void)updateViewConstraints { [super updateViewConstraints]; // constraints for portrait orientation // use a property to change a constraint constant and/or create constraints programmatically, eg: if (!self.layoutConstraintsPortrait) { UIView *image1 = self.image1; UIView *image2 = self.image2; self.layoutConstraintsPortrait = [[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy]; [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem: image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; [self.layoutConstraintsPortrait addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; } // constraints for landscape orientation // make sure they don't conflict with and complement the existing constraints if (!self.layoutConstraintsLandscape) { UIView *image1 = self.image1; UIView *image2 = self.image2; self.layoutConstraintsLandscape = [[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[image1]-[image2]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(image1, image2)] mutableCopy]; [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image1 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:image1.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; [self.layoutConstraintsLandscape addObject:[NSLayoutConstraint constraintWithItem:image2 attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem: image2.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; } BOOL isPortrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation); [self.view removeConstraints:isPortrait ? self.layoutConstraintsLandscape : self.layoutConstraintsPortrait]; [self.view addConstraints:isPortrait ? self.layoutConstraintsPortrait : self.layoutConstraintsLandscape]; } 

Now all you have to do is initiate a constraint update whenever the situation changes. Override willAnimateRotationToInterfaceOrientation:duration: to animate updates to constraints when changing orientation:

 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; [self.view setNeedsUpdateConstraints]; } 
+38
Nov 01 '13 at 1:33
source share

The approach I use (for better or worse) is to define both sets of constraints (portrait and landscape) in the storyboard editor.

To avoid adrenaline alerts, I put all one set with a priority of 999, so that it does not appear everywhere in red.

Then I add all the restrictions to the output collections:

 @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *portraitConstraints; @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *landscapeConstraints; 

Finally, I implement my ViewControllers viewWillLayout method:

 - (void) viewWillLayoutSubviews { [super viewWillLayoutSubviews]; for (NSLayoutConstraint *constraint in self.portraitConstraints) { constraint.active = (UIApplication.sharedApplication.statusBarOrientation == UIDeviceOrientationPortrait); } for (NSLayoutConstraint *constraint in self.landscapeConstraints) { constraint.active = (UIApplication.sharedApplication.statusBarOrientation != UIDeviceOrientationPortrait); } } 

It seems to work. I really wish you could set the default active property in the storyboard editor.

+16
Dec 29 '15 at 23:51
source share

I follow the same approach as yours (without nib files or storyboard). You must update your restrictions in the updateViewConstraints method (by checking the device orientation). There is no need to call setNeedsUpdateConstraints in updateViewConstraints , because as soon as you change the orientation of the device, the last method is called automatically.

+2
Dec 03 '13 at 10:28
source share

You can save your restrictions to a property or variable as portrait and landscape versions, and then set and remove them when rotating.

I did this by making my xib restrictions for the initial view, assigning them to the output points in the view controller. When turning, I create alternative restrictions, delete sockets, but save them, insert alternatives.

Cancel the process when turning back.

0
Jul 21 '13 at 13:59 on
source share

My idea is to handle orientation by changing the priorities of the constraints.
Estimated priorities will be:

  • landscape: 910 active / 10 inactive.
  • Portrait: 920 active / 20 inactive.

Step 1: Create a landscape (or portrait) design in a constrained storyboard.
Step 2: For restrictions that should only be active for landscape mode, set the priority to 10.
Step 3: Add restrictions for portrait mode and set their priority to 920.

In willAnimateRotationToInterfaceOrientation add code:

 for (NSLayoutConstraint *constraint in myView.constraints) { if (UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication.statusBarOrientation)) { if (constraint.priority == 10) constraint.priority = 910; if (constraint.priority == 920) constraint.priority = 20; } else { if (constraint.priority == 20) constraint.priority = 920; if (constraint.priority == 910) constraint.priority = 10; } } 

The advantage of this approach is its easy configuration in Interface Builder. When we need to switch to any orientation, we select all the restrictions by priority and at the same time change them (910-> 10, 20-> 920):

enter image description here

The interface will be automatically restored.

-one
Dec 09 '16 at 17:55
source share



All Articles