Repositioning controls when the orientation changes

后端 未结 5 436
醉酒成梦
醉酒成梦 2021-02-04 09:01

I know Auto Layout can be used to make the sizes and position consistent when the orientation changes. Is it possible to completely change the layout when the orientation change

相关标签:
5条回答
  • 2021-02-04 09:19

    In your case it can be achieved by two methods, instead of reframing every component you can group the controls like the following..

    1. Parent View -> User Info View -> All User Info controls.. By doing this you will have to just reframe the User Info View not all the controls..

      Then only Logo and Company name left to reframe.. Total 3 controls to reframe if you group your controls..

    2. Create two views one for Portrait and other for Landscape mode, and just add and remove on rotations.. this is the fastest way as you won't have to readjust the frame by tedious code.

    Hope above helps.

    0 讨论(0)
  • 2021-02-04 09:24

    When using autolayout you can override updateViewConstraints to modify the layout on orientation change:

    - (void)updateViewConstraints{
    
      [super updateViewConstraints];
      //portrait
      if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
    
      }
      //landscape
      else{
        //
      }
    }
    
    0 讨论(0)
  • 2021-02-04 09:25

    you cant set frames differently : -

    -(void)setFramesForPotrait
    {
    
    // set frames here
    
    }
    
    -(void)setFramesForLandscaeMode
    {
    
    // set frames here
    
    }
    
    -(bool)shouldAutorotate.....
    {
    return Yes
    }
    
    -()willAutoRotate......
    {
    if(orientation = uiinterfaceOrientationPotrait)
    {
    [self setFramesForPotrait];
    }
    else
    {
    [self setFramesForLandscape];
    }
    
    0 讨论(0)
  • 2021-02-04 09:32

    I've had the same problem and here's what I've found so far. The approach I'm using is having two sets (potentially multiple) sets of constraints for different screen sizes or orientations. So I just design for portrait and connect all constraints that are portrait-specific to a IBOutletCollection: enter image description here Then switch the VC orientation in InterfaceBuilder to Landscape and add the required constraints for this orientation and connect to the corresponding outlet: enter image description here

    Then in code I'm removing or adding the constraints as required:

    - (void)viewWillLayoutSubviews
    {
        [super viewWillLayoutSubviews];
        [self updateViewConstraints];
    }
    
    - (void)updateViewConstraints
    {
        [super updateViewConstraints];
        if (self.view.frame.size.width >= kSize * 2 + kPadding * 3)
        {
            [self.view removeConstraints:self.constraintsForPortrait];
            [self.view addConstraints:self.constraintsForLandscape];
        } else
        {
            [self.view removeConstraints:self.constraintsForLandscape];
            [self.view addConstraints:self.constraintsForPortrait];
        }
    }
    

    You can achieve similar results with this code, basing your adding/removing of constraints on orientation instead of frame size:

    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
        [self updateViewConstraints];
    }
    

    But keeping in mind that Apple is rumored to release devices with different screen aspect ratios and obsoleting the UIInterfaceOrientation and rotation events, it might be worth preparing in advance. Will see what future brings.

    The downside of the approach is that that Xcode will be complaining about the design being ambiguous, which it actually is, since Xcode doesn't know we'll be removing the ambiguity at runtime. To tackle that you could set the priority of the constraints to be optional for all other orientations that you're not designing for at this particular moment (e.g. if you're designing for Portrait then optionalize the constraints for Landscape).

    0 讨论(0)
  • 2021-02-04 09:42

    It can be done with layout constraints something like I have below. This doesn't quite work, because your sketch doesn't quite work -- your landscape view is too long compared with what you really get in landscape. You would have to shorten the login text fields for everything to fit, but this should give you an idea how it's done. The buttonWidth constraint shows how to have a negative correlation between the width of the view and the width of a button -- that is, the button's width will be less in landscape than in portrait. I have several IBOutlets to constraints that I reference in the code. I can describe them for you if you're interested, but I'll just throw this out there for now:

    @implementation ViewController {
        IBOutlet NSLayoutConstraint *buttonWidth;
        IBOutlet NSLayoutConstraint *logoTop;
        IBOutlet NSLayoutConstraint *logoAlignToLabel;
        IBOutlet NSLayoutConstraint *logoSpaceToLabel;
        IBOutlet NSLayoutConstraint *coNameToButtonAlignment;
        IBOutlet UIButton *b;
        IBOutlet UIImageView *logo;
        IBOutlet UILabel *coName;
        NSLayoutConstraint *con2;
        NSArray *cons1;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [b removeConstraint:buttonWidth];
        buttonWidth = [NSLayoutConstraint constraintWithItem:b attribute:NSLayoutAttributeWidth relatedBy:0 toItem:self.view attribute:NSLayoutAttributeWidth multiplier:-.2193 constant:350];
        [self.view addConstraint:buttonWidth];
        [self.view layoutSubviews];
    }
    
    - (void)updateViewConstraints{
        [super updateViewConstraints];
        if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
            if (con2 != nil) {
                [self.view removeConstraints:cons1];
                [self.view removeConstraint:con2];
                [self.view addConstraints:@[logoAlignToLabel,logoSpaceToLabel,logoTop,coNameToButtonAlignment]];
            }
        }else{
            NSLog(@"Landscape");
            [self.view removeConstraints:@[logoAlignToLabel,logoSpaceToLabel,logoTop,coNameToButtonAlignment]];
            cons1 = [NSLayoutConstraint constraintsWithVisualFormat:@"|-8-[logo]-4-[coName]" options:NSLayoutFormatAlignAllCenterY metrics:0 views:@{@"logo":logo, @"coName":coName}];
            con2 = [NSLayoutConstraint constraintWithItem:logo attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
            [self.view addConstraints:cons1];
            [self.view addConstraint:con2];
        }
    }
    

    On rotation the logo and company name label have their constraints removed, and new ones put in place. The new constraint for the button, that I put on in viewDidLoad, takes care of rotation automatically, so I don't have to adjust it at all during the rotation.

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