IOS AutoLayout Change position on Rotation

后端 未结 2 444
自闭症患者
自闭症患者 2021-01-16 10:47

I wanted to sent one container below the other on portrait and side by side on landscape. Is it possible with just auto layout? I know i can do it programmatically, just won

相关标签:
2条回答
  • 2021-01-16 11:17

    Well didRotateFromInterfaceOrientation is not the preferred way to do these kind of things with iOS 8. I would suggest you to take a look at traitCollection and view controller methods associated with it. The trick here is to install horizontal constraint or vertical constraint when UIViewController method viewWillTransitionToSize:withTransitionCoordinator: trigger.

    Here is the way I did it,

    @interface ViewController ()
    
    @property (nonatomic, weak) UIView *aContainerView;
    @property (nonatomic, weak) UIView *bContainerView;
    
    @property (nonatomic, strong) NSArray *horizontalOrientationConstraints;
    @property (nonatomic, strong) NSArray *verticalOrientationConstraints;
    
    @end
    
    @implementation ViewController
    
    #pragma mark - Getters
    
    - (NSArray *)horizontalOrientationConstraints
    {
        if (!_horizontalOrientationConstraints) {
            NSLayoutConstraint *equalWidthConstraints = [NSLayoutConstraint constraintWithItem:self.aContainerView
                                                                                     attribute:NSLayoutAttributeWidth
                                                                                     relatedBy:NSLayoutRelationEqual
                                                                                        toItem:self.bContainerView
                                                                                     attribute:NSLayoutAttributeWidth
                                                                                    multiplier:1.0
                                                                                      constant:0];
    
            NSArray *vConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[aContainerView][bContainerView]|"
                                                                            options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom
                                                                            metrics:nil views:@{@"aContainerView": self.aContainerView, @"bContainerView": self.bContainerView}];
            NSArray *hConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[aContainerView]|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:@{@"aContainerView": self.aContainerView}];
            NSArray *constraints = [vConstraints arrayByAddingObjectsFromArray:hConstraints];
            _horizontalOrientationConstraints = [constraints arrayByAddingObject:equalWidthConstraints];
    
        }
        return _horizontalOrientationConstraints;
    }
    
    
    - (NSArray *)verticalOrientationConstraints
    {
        if (!_verticalOrientationConstraints) {
            NSLayoutConstraint *equalHeightConstraints = [NSLayoutConstraint constraintWithItem:self.aContainerView
                                                                                      attribute:NSLayoutAttributeHeight
                                                                                      relatedBy:NSLayoutRelationEqual
                                                                                         toItem:self.bContainerView
                                                                                      attribute:NSLayoutAttributeHeight
                                                                                     multiplier:1.0
                                                                                       constant:0];
    
    
            NSArray *vConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[aContainerView][bContainerView]|"
                                                                            options:NSLayoutFormatAlignAllLeft | NSLayoutFormatAlignAllRight
                                                                            metrics:nil views:@{@"aContainerView": self.aContainerView, @"bContainerView": self.bContainerView}];
            NSArray *hConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[aContainerView]|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:@{@"aContainerView": self.aContainerView}];
            NSArray *constraints = [vConstraints arrayByAddingObjectsFromArray:hConstraints];
            _verticalOrientationConstraints = [constraints arrayByAddingObject:equalHeightConstraints];
    
        }
        return _verticalOrientationConstraints;
    }
    
    #pragma mark - 
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        UIView *aContainerView = [self viewWithLabelText:@"A" andBackgroundColor:[UIColor yellowColor]];
        UIView *bContainerView = [self viewWithLabelText:@"B" andBackgroundColor:[UIColor greenColor]];
    
        [self.view addSubview:aContainerView];
        [self.view addSubview:bContainerView];
    
        self.aContainerView = aContainerView;
        self.bContainerView = bContainerView;
    
        CGSize viewSize = self.view.bounds.size;
    
        if (viewSize.width > viewSize.height) {
            [NSLayoutConstraint activateConstraints:self.horizontalOrientationConstraints];
        } else {
            [NSLayoutConstraint activateConstraints:self.verticalOrientationConstraints];
        }
    }
    
    - (UIView *)viewWithLabelText:(NSString *)text andBackgroundColor:(UIColor *)color
    {
        UIView *aContainerView = [[UIView alloc] init];
        aContainerView.backgroundColor = [UIColor blackColor];
        aContainerView.translatesAutoresizingMaskIntoConstraints = NO;
    
        UIView *aView = [[UIView alloc] init];
        aView.translatesAutoresizingMaskIntoConstraints = NO;
        aView.backgroundColor = color;
    
        UILabel *aLabel = [[UILabel alloc] init];
        aLabel.translatesAutoresizingMaskIntoConstraints = NO;
        aLabel.text = text;
        aLabel.font = [UIFont systemFontOfSize:80];
    
        [aView addSubview:aLabel];
    
        [aContainerView addSubview:aView];
    
    
        NSLayoutConstraint *centerXConstraints = [NSLayoutConstraint constraintWithItem:aView
                                                                              attribute:NSLayoutAttributeCenterX
                                                                              relatedBy:NSLayoutRelationEqual
                                                                                 toItem:aLabel
                                                                              attribute:NSLayoutAttributeCenterX
                                                                             multiplier:1.0
                                                                               constant:0];
        NSLayoutConstraint *centerYConstraints = [NSLayoutConstraint constraintWithItem:aView
                                                                              attribute:NSLayoutAttributeCenterY
                                                                              relatedBy:NSLayoutRelationEqual
                                                                                 toItem:aLabel
                                                                              attribute:NSLayoutAttributeCenterY
                                                                             multiplier:1.0
                                                                               constant:0];
        [aContainerView addConstraints:@[centerXConstraints, centerYConstraints]];
    
    
        NSString *hConstraintsFormat = @"V:|-10-[view]-10-|";
        NSString *vConstraintsFormat = @"H:|-10-[view]-10-|";
    
        [aContainerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:hConstraintsFormat
                                                                                    options:0
                                                                                    metrics:nil
                                                                                      views:@{@"view": aView}]];
        [aContainerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vConstraintsFormat
                                                                                    options:0
                                                                                    metrics:nil
                                                                                      views:@{@"view": aView}]];
    
        return aContainerView;
    }
    
    
    
     - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
    {
        NSArray *constraintsToDeactivate;
        NSArray *constraintsToActivate;
    
        if (size.width > size.height) {
            constraintsToActivate = self.horizontalOrientationConstraints;
            constraintsToDeactivate = self.verticalOrientationConstraints;
        } else {
            constraintsToActivate = self.verticalOrientationConstraints;
            constraintsToDeactivate = self.horizontalOrientationConstraints;
        }
    
        [NSLayoutConstraint deactivateConstraints:constraintsToDeactivate];
        [NSLayoutConstraint activateConstraints:constraintsToActivate];
        [self.view layoutIfNeeded];
    }
    
    @end
    

    Here is how it looks for both the orientations,

    enter image description here

    enter image description here

    For iOS7, you basically do the same thing. Instead of overriding viewWillTransitionToSize: you should rather override willAnimateRotationToInterfaceOrientation:duration:. Then you add or remove the constraint inside the method,

    @interface ViewController ()
    
    @property (nonatomic, weak) UIView *aContainerView;
    @property (nonatomic, weak) UIView *bContainerView;
    
    @property (nonatomic, assign) BOOL touchExited;
    @property (nonatomic, assign) NSUInteger count;
    @property (nonatomic, weak) NSTimer *countChangeTimer;
    @property (nonatomic, weak) UIButton *theCountButton;
    
    @property (nonatomic, strong) NSArray *horizontalOrientationConstraints;
    @property (nonatomic, strong) NSArray *verticalOrientationConstraints;
    
    @end
    
    @implementation ViewController
    
    #pragma mark - Getters
    
    - (NSArray *)horizontalOrientationConstraints
    {
        if (!_horizontalOrientationConstraints) {
            NSLayoutConstraint *equalWidthConstraints = [NSLayoutConstraint constraintWithItem:self.aContainerView
                                                                                     attribute:NSLayoutAttributeWidth
                                                                                     relatedBy:NSLayoutRelationEqual
                                                                                        toItem:self.bContainerView
                                                                                     attribute:NSLayoutAttributeWidth
                                                                                    multiplier:1.0
                                                                                      constant:0];
    
            NSArray *vConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[aContainerView][bContainerView]|"
                                                                            options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom
                                                                            metrics:nil views:@{@"aContainerView": self.aContainerView, @"bContainerView": self.bContainerView}];
            NSArray *hConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[aContainerView]|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:@{@"aContainerView": self.aContainerView}];
            NSArray *constraints = [vConstraints arrayByAddingObjectsFromArray:hConstraints];
            _horizontalOrientationConstraints = [constraints arrayByAddingObject:equalWidthConstraints];
    
        }
        return _horizontalOrientationConstraints;
    }
    
    
    - (NSArray *)verticalOrientationConstraints
    {
        if (!_verticalOrientationConstraints) {
            NSLayoutConstraint *equalHeightConstraints = [NSLayoutConstraint constraintWithItem:self.aContainerView
                                                                                      attribute:NSLayoutAttributeHeight
                                                                                      relatedBy:NSLayoutRelationEqual
                                                                                         toItem:self.bContainerView
                                                                                      attribute:NSLayoutAttributeHeight
                                                                                     multiplier:1.0
                                                                                       constant:0];
    
    
            NSArray *vConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[aContainerView][bContainerView]|"
                                                                            options:NSLayoutFormatAlignAllLeft | NSLayoutFormatAlignAllRight
                                                                            metrics:nil views:@{@"aContainerView": self.aContainerView, @"bContainerView": self.bContainerView}];
            NSArray *hConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[aContainerView]|"
                                                                            options:0
                                                                            metrics:nil
                                                                              views:@{@"aContainerView": self.aContainerView}];
            NSArray *constraints = [vConstraints arrayByAddingObjectsFromArray:hConstraints];
            _verticalOrientationConstraints = [constraints arrayByAddingObject:equalHeightConstraints];
    
        }
        return _verticalOrientationConstraints;
    }
    
    #pragma mark -
    
    - (void)invalidateTimer
    {
        if (self.countChangeTimer) {
            [self.countChangeTimer invalidate];
        }
    }
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        UIView *aContainerView = [self viewWithLabelText:@"A" andBackgroundColor:[UIColor yellowColor]];
        UIView *bContainerView = [self viewWithLabelText:@"B" andBackgroundColor:[UIColor greenColor]];
    
        [self.view addSubview:aContainerView];
        [self.view addSubview:bContainerView];
        self.aContainerView = aContainerView;
        self.bContainerView = bContainerView;
    
        CGSize viewSize = self.view.bounds.size;
    
        if (viewSize.width > viewSize.height) {
            [self.view addConstraints:self.horizontalOrientationConstraints];
        } else {
            [self.view addConstraints:self.verticalOrientationConstraints];
        }
    }
    
    - (UIView *)viewWithLabelText:(NSString *)text andBackgroundColor:(UIColor *)color
    {
        UIView *aContainerView = [[UIView alloc] init];
        aContainerView.backgroundColor = [UIColor blackColor];
        aContainerView.translatesAutoresizingMaskIntoConstraints = NO;
    
        UIView *aView = [[UIView alloc] init];
        aView.translatesAutoresizingMaskIntoConstraints = NO;
        aView.backgroundColor = color;
    
        UILabel *aLabel = [[UILabel alloc] init];
        aLabel.translatesAutoresizingMaskIntoConstraints = NO;
        aLabel.text = text;
        aLabel.font = [UIFont systemFontOfSize:80];
    
        [aView addSubview:aLabel];
    
        [aContainerView addSubview:aView];
    
    
        NSLayoutConstraint *centerXConstraints = [NSLayoutConstraint constraintWithItem:aView
                                                                              attribute:NSLayoutAttributeCenterX
                                                                              relatedBy:NSLayoutRelationEqual
                                                                                 toItem:aLabel
                                                                              attribute:NSLayoutAttributeCenterX
                                                                             multiplier:1.0
                                                                               constant:0];
        NSLayoutConstraint *centerYConstraints = [NSLayoutConstraint constraintWithItem:aView
                                                                              attribute:NSLayoutAttributeCenterY
                                                                              relatedBy:NSLayoutRelationEqual
                                                                                 toItem:aLabel
                                                                              attribute:NSLayoutAttributeCenterY
                                                                             multiplier:1.0
                                                                               constant:0];
        [aContainerView addConstraints:@[centerXConstraints, centerYConstraints]];
    
    
        NSString *hConstraintsFormat = @"V:|-10-[view]-10-|";
        NSString *vConstraintsFormat = @"H:|-10-[view]-10-|";
    
        [aContainerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:hConstraintsFormat
                                                                                    options:0
                                                                                    metrics:nil
                                                                                      views:@{@"view": aView}]];
        [aContainerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:vConstraintsFormat
                                                                                    options:0
                                                                                    metrics:nil
                                                                                      views:@{@"view": aView}]];
    
        return aContainerView;
    }
    
    - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
    duration:(NSTimeInterval)duration{
        NSArray *constraintsToDeactivate;
        NSArray *constraintsToActivate;
    
            if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
                constraintsToActivate = self.horizontalOrientationConstraints;
                constraintsToDeactivate = self.verticalOrientationConstraints;
            } else {
                constraintsToActivate = self.verticalOrientationConstraints;
                constraintsToDeactivate = self.horizontalOrientationConstraints;
            }
            [self.view removeConstraints:constraintsToDeactivate];
            [self.view addConstraints:constraintsToActivate];
    
    }
    
    @end
    
    0 讨论(0)
  • 2021-01-16 11:17

    Yep, I think there is going to be a little code though. So the I believe the 2 constraints involved here are horizontal spacing and vertical spacing (Editor -> Pin -> Horizontal/Vertical).

    Arrange A and B in the portrait layout, select both of the elements, and add both of those constraints. Create IBOutlets to both of these constraints in the header file (just like you would a label, button, etc)

    You can then change the values of these constraints in the "didRotateFromInterfaceOrientation" delegate method (constraint_variable_name.constant = 0;). Let me know if any of this is unclear or you need me to elaborate on any part of it.

    0 讨论(0)
提交回复
热议问题