Repositioning controls when the orientation changes

不问归期 提交于 2019-12-20 10:35:19

问题


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 changes?

For example, please look at the below wire-frame of a simple login screen in portrait mode.

Now if I rotate the device, I want to completely re-position the controls.

Can this kind of a thing be done by using Auto Layout? If not, how should I go about this?

Thank you.


回答1:


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.




回答2:


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];
}



回答3:


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:

Then switch the VC orientation in InterfaceBuilder to Landscape and add the required constraints for this orientation and connect to the corresponding outlet:

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).




回答4:


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{
    //
  }
}



回答5:


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.



来源:https://stackoverflow.com/questions/14929207/repositioning-controls-when-the-orientation-changes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!