Search code examples
iosobjective-cautolayout

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


In portrait mode, I have a tableview on the left-side, and a webview on the right-side. They both take half of the screen. I have autolayout enabled.

But when I rotate the screen to landscape mode, the tableview's width takes up less than half the screen's size, and the webview ends up taking more, instead of them being an even split.

Why does this happen? How can I have the views take up only half the screen in regard to their widths, regardless of screen orientation?


Solution

  • 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:

    enter image description here

    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:

    enter image description here

    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:

    enter image description here

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

    Step 3:

    enter image description here

    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:

    enter image description here

    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:

    enter image description here

    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.

    enter image description here

    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:

    enter image description here

    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.

    enter image description here

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