OgreSwamp
OgreSwamp

Reputation: 4692

Different sets of auto layout constraints for different orientation

I've seen similar post but it isn't really close to my case

So I have different screen layouts for different orientations. App is using storyboards. To have a better understanding I attach photo of the UI sketch UI Sketch

As you can see there is a TableView and a Toolbar (a custom one). Toolbar contains 2 labels and a button.

So portrait constraints are:

Landscape constraints are totally different:

I've tried to delete all constraints from storyboard and add them programmatically. But Xcode add them during compilation automatically. I've tried to delete all constraints inside root view but probably I didn't go properly through all views tree as several constrains aren't deleted.

Do you have any idea how that can be implemented in a proper way?

This is my first experience with Auto Layout and it isn't that easy as I expected.

Here my solution which doesn't work (as Xcode adds some constraints during compilation)

// Those properties store all constraints for portrait and landscape modes
@property (nonatomic, strong) NSArray *portraitConstraints;
@property (nonatomic, strong) NSArray *landscapeConstraints;

-(void)updateViewConstraints {
    [super updateViewConstraints];

    BOOL layoutIsPortrait = UIDeviceOrientationIsPortrait(self.interfaceOrientation);

    if (layoutIsPortrait) {
        for (NSLayoutConstraint *constraint in self.landscapeConstraints)
            [constraint remove];

        for (NSLayoutConstraint *constraint in self.portraitConstraints)
            [constraint install];
    } else {
        for (NSLayoutConstraint *constraint in self.portraitConstraints)
            [constraint remove];

        for (NSLayoutConstraint *constraint in self.landscapeConstraints)
            [constraint install];
    }

}

- (NSArray *)portraitConstraints {
    if (!_portraitConstraints) {
        UIView *mainTable = self.myTableView;
        UIView *toolbar = self.toolbarView;
        UIView *firstLabel = self.firstLabel;
        UIView *secondLabel = self.secondLabel;
        UIView *bigButton = self.bigButton;
        UIView *navBar = self.navigationController.navigationBar;

        NSDictionary *views = NSDictionaryOfVariableBindings(mainTable,toolbar,firstLabel,secondLabel,bigButton,navBar);

        NSMutableArray *constraints = [NSMutableArray array];
        [constraints addObjectsFromArray:[NSLayoutConstraint
                                          constraintsWithVisualFormat:@"V:[toolbar(==80)]|"
                                          options:0
                                          metrics:nil
                                          views:views]];
        [constraints addObjectsFromArray:[NSLayoutConstraint
                                          constraintsWithVisualFormat:@"V:[navBar][mainTable][toolbar]|"
                                          options:0
                                          metrics:nil
                                          views:views]];
        // MORE AND MORE CONSTRAINTS ADDED HERE

        _portraitConstraints = constraints;
    }
    return _portraitConstraints;
}

Upvotes: 3

Views: 1878

Answers (1)

rdelmar
rdelmar

Reputation: 104082

The approach you're using is certainly possible, but will involve quite a bit of code to get the layout you're looking for. An easier way to to this would be to delete your controller's view in the storyboard (you can copy and paste it into the xib file if you want), and instead make its views, one each for portrait and landscape, in a xib file. You can do all you constraint setup there, and only have to switch between the two views in code. You can create both views in one xib file -- I created the portrait one first, so it will be the first object in the array you get back from loading the nib.

@interface ViewController ()
@property (strong,nonatomic) UIView *pView;;
@property (strong,nonatomic) UIView *lView;
@property (strong,nonatomic) UILabel *leftLabel;
@property (strong,nonatomic) UILabel *rightLabel;
@end

@implementation ViewController

- (void)loadView {
    NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"PortraitAndLandscapeViews" owner:self options:nil];
    self.pView = views[0];
    self.lView = views[1];
    self.view = self.pView;
}



-(void)viewWillLayoutSubviews {
    BOOL layoutIsPortrait = UIDeviceOrientationIsPortrait(self.interfaceOrientation);
    if (layoutIsPortrait) {
        self.view = self.pView;
        self.leftLabel = [self.view viewWithTag:11];
        self.rightLabel = [self.view viewWithTag:12];
    }else{
        self.view = self.lView;
        self.leftLabel = [self.view viewWithTag:21];
        self.rightLabel = [self.view viewWithTag:22];
    }
}

Upvotes: 2

Related Questions