How to Rearrange Views When Autorotating with Autolayout

iOS 7 - Autolayout - How to change location of views when rotating

OK there are several approaches.

First approach: using autolayout in a smart way

So you know how wide the square will be and that it will be stuck to the left and top. So set up you autolayouts that it sets left and top offset and width and height. The buttons are stuck y pixels from the bottom and x from the right and have a fixed width and height. Those constraints can always be satisfied.

This works fine for a single idiom like iPad or iPhone.

To get the 290 instead of 300 you need to set an offset to the bottom as well that says > 10 with a priority of say 1000 while the height of <=300 has a priority of 750 and a height of >= 250 (or whatever you like) has a priority of 1000 again. I should play around in a real storyboard to test that correctly, it's not the easiest thing to set up without warnings or problems.

I ended up setting it up with a lot of soft sizes with priorities. The 290 px height has a priority of just 250 for example.

Set up

Second approach: flexible size layouts

Next approach is for the new, unlimited sized idiom that is in Xcode 6 already. Clearly this is the future and I would suggest to adapt your app to that. You will have to tell me more about your application and how you want it to scale because there is no real concept of size anymore, just an idea of where the widest and where the narrowest part is.

iOS: autolayout move view from left to top right

It can be easily done using Size Classes , take a look at apple doc Size Classes design help

This feature available only in xCode 6 New Features in xCode 6.

Constraints in w**Any** h**Any** layout

Constraints in w**Any** h**Compact** layout

Keep the same Constraints for other layouts.

Note that Gray coloured constraints are not installed for present layout.

You can find the sample in the link DownLoad Sample

iOS change auto layout constraints when device rotates

In willRotateToInterfaceOrientation:duration:, send setNeedsUpdateConstraints to any view that needs its constraints modified.

Alternatively, make a UIView subclass. In your subclass, register to receive UIApplicationWillChangeStatusBarOrientationNotification. When you receive the notification, send yourself setNeedsUpdateConstraints.

This sets the needsUpdateConstraints flag on the view. Before the system performs layout (by sending layoutSubviews messages), it sends an updateConstraints message to any view that has the needsUpdateConstraints flag set. This is where you should modify your constraints. Make a UIView subclass and override updateConstraints to update your constraints.

Changing Auto Layout constraints for orientation

I appear to have solved it. See this article and PureLayout. Basically:

  • Implement a method something like -(void)updateConstraintsForSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator;
  • In this method, if you've rotated (store the state somewhere), uninstall all your constraints and generate new ones. If you have a coordinator, install them and [self.view layoutIfNeeded] in the coordinator's animateAlongsideTransition block parameter. Otherwise just install and layout.
  • Override viewDidLayoutSubviews and call this method with self.view.bounds.size and nil
  • Override viewWillTransitionToSize:withTransitionCoordinator: and call your method appropriately

In autolayout, how can I have view take up half of the screen, regardless of orientation?

The first half of the answer address the case in which we want to split the view evenly between view A (blue) and view B (red). The second half will address the case in which we want to have view A take up half the screen, but view B does not exist.

Step 1:

Sample Image

Set up blue's auto-layout constraints as pictured. Top, left, bottom of 0 to the superview. Right of 0 to the red view.

Step 2:

Sample Image

Set up the same, but mirrored, constraints for the red view.

If you've completed the first two steps correctly, you should have some auto-layout errors and warnings:

Sample Image

We need one more constraint to fix these errors/warnings and get what we need.

Step 3:

Sample Image

Hold control, click and drag from one view to the other and select "equal widths". Now our views will always maintain the same width. All of our auto layout warnings and errors disappear, and our views will always be half the screen no matter the orientation or device.

To add these constraints in code using VFL, we need the following constraints:

@"H:|[blueView(==redView)][redView]|"
@"V:|[blueView]|"
@"V:|[redView]|"

Now, suppose the case where we want a single view to take up half the screen, but we don't have a view for the other half. We can still do this with auto layout, but it's a slightly different set up. In this example, our view is blue, and its parent view is green.

Step 1:

Sample Image

This is similar to step 1 above, except we don't add a right side constraint (this will obviously vary if we want our view to take up a different half).

Step 2:

Sample Image

Like before, we want to assign an "equal widths" constraint. In this case, from our view to the parent view. Again, hold control and click drag from one to the other.

Sample Image

At this point, we have an auto layout warning. Auto layout wants our frame to match its parent's width. Clicking the warning and choosing "Update constraints" will put a hardcoded value in. We don't want this.

Step 3:

Sample Image

Select the view and go to its size inspector. Here, we'll be able to edit the constraints.

Click "Edit" next to the "Equal Width to:" constraint. We need to change the multiplier value.

Sample Image

We need to change the multiplier value to 2.

The constraint now changes to a "Proportional Width to:", and all of our auto layout warnings and errors disappear. Now our view will always take up exactly half of the super view.

To add these constraints in code, we can add some using VFL:

@"H:|[blueView]"
@"V:|[blueView]|"

But the proportional width constraint can't be added with VFL. We must add it as such:

NSLayoutConstraint *constraint =
[NSLayoutConstraint constraintWithItem:blueView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:superView
attribute:NSLayoutAttributeWidth
multiplier:2.0
constant:0.0];

How to setup autolayout so UILabel resizes and other views move as necessary

If I understand it correctly there two things that you are looking for:

  1. Resize the label based on the text length using storyboard, this can be achieved by going into the attribute inspector and setting Lines to 0 and Line break Mode to WordWrap. Also attached a picture for reference
    here.
    Just some extra info, you can also be achieve it programmatically, by using the code below:

    myLabel.numberOfLines = 0
    myLabel.lineBreakMode = .byWordWrapping
  2. Moving other views based on the size of your label, this can be achieved by setting up constraints against the views that you want to be pushed. You can refer to Apple's documentation here, easy to grasp and shows how to do it step by step.

Different layout in landscape using Autolayout

You need to add separate constraints for both landscape/portrait orientation. See the following example it will help you. Here i have added constraints for one textfield only.

textfld1.translatesAutoresizingMaskIntoConstraints = NO;

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[textfld1 removeConstraints:textfld1.constraints];
[self.view removeConstraints:self.view.constraints];

if (toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {

//You can use either center horizontally or Leading
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:textfld1
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:234.0]];

// // Center horizontally
// [self.view addConstraint:[NSLayoutConstraint constraintWithItem:textfld1
// attribute:NSLayoutAttributeCenterX
// relatedBy:NSLayoutRelationEqual
// toItem:self.view
// attribute:NSLayoutAttributeCenterX
// multiplier:1.0
// constant:0.0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:textfld1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:100.0]];

}else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight){

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:textfld1
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:120.0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:textfld1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:140.0]];

}

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:textfld1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:30]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:textfld1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:300]];

}

How to keep the same spacing when rotating the screen? (Autolayout)

I found the solution. I just put vertical spacing between the labels and superview. I put the bottom label vertical constraint at 500 priority, and made sure that all the labels had vertical hugging priority of 501.



Related Topics



Leave a reply



Submit