问题
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?
回答1:
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:
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:
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:
We need one more constraint to fix these errors/warnings and get what we need.
Step 3:
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:
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:
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.
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:
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.
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];
回答2:
Create a UIView
in XIB
or Storyboard
- Set top and left constraints
- Set a height constraint
- Set width constraint to equal width of the super view *Important
- Edit the width of the constraint by converting it to decimal
- Set the decimal to the width you'd like (In my case 0.5 or half)
回答3:
Bind both of them to the superview edges (table view to the leading edge, web view to the trailing edge) and set constraint for them to have same width.
回答4:
Programatically in Swift 4:
import UIKit
class ViewController: UIViewController {
let halfScreenViewLeft: UIView = {
let view = UIView()
view.backgroundColor = .blue
return view
}()
let halfScreenViewRight: UIView = {
let view = UIView()
view.backgroundColor = .red
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(halfScreenViewLeft)
view.addSubview(halfScreenViewRight)
//Enable Autolayout
halfScreenViewLeft.translatesAutoresizingMaskIntoConstraints = false
//Place the top side of the view to the top of the screen
halfScreenViewLeft.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
//Place the left side of the view to the left of the screen.
halfScreenViewLeft.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
//Set the width of the view. The multiplier indicates that it should be half of the screen.
halfScreenViewLeft.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5).isActive = true
//Set the same height as the view´s height
halfScreenViewLeft.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
//We do the same for the right view
//Enable Autolayout
halfScreenViewRight.translatesAutoresizingMaskIntoConstraints = false
//Place the top side of the view to the top of the screen
halfScreenViewRight.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
//The left position of the right view depends on the position of the right side of the left view
halfScreenViewRight.leadingAnchor.constraint(equalTo: halfScreenViewLeft.trailingAnchor).isActive = true
//Place the right side of the view to the right of the screen.
halfScreenViewRight.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
//Set the same height as the view´s height
halfScreenViewRight.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
}
}
回答5:
The constraint system can't read your mind. You must say what you want. Half is half. If you want half, say half. To make a view half the width of its superview, give it a width constraint that has a multiplier of .5
in relation to its superview's width.
来源:https://stackoverflow.com/questions/26896844/in-autolayout-how-can-i-have-view-take-up-half-of-the-screen-regardless-of-ori