在自动布局中,无论方向如何,我该如何让视图占据屏幕的一半?

31
在竖屏模式下,左侧是一个tableView,右侧是webView,两个视图各占屏幕的一半,并启用了自动布局。
但是当我将屏幕旋转到横屏模式时,tableView的宽度仅占屏幕大小的一半以下,而webView却占据了更多的空间,导致它们不再均匀分配。
这是为什么?无论屏幕方向如何,如何才能使这些视图的宽度仅占屏幕宽度的一半?

5个回答

81

答案的前半部分处理了我们想要将视图 A(蓝色)和视图 B(红色)平均分割的情况。后半部分将处理我们想让视图 A 占据半个屏幕,但视图 B 不存在的情况。

步骤 1:

enter image description here

按照图片设置蓝色视图的自动布局约束条件。顶部、左侧、底部为 0 对于父视图。右侧为 0 对于红色视图。

步骤 2:

enter image description here

为红色视图设置相同但镜像的约束条件。

如果你正确完成了前两个步骤,应该会出现一些自动布局错误和警告:

enter image description here

我们需要一个额外的约束条件来解决这些错误/警告并得到我们所需的效果。

步骤 3:

enter image description here

按住 Control 键,从一个视图向另一个视图拖动并选择“宽度相等”。现在我们的视图将始终保持相同的宽度。所有自动布局警告和错误都消失了,无论方向或设备如何,我们的视图都将占据屏幕的一半。

要使用 VFL 以编程方式添加这些约束条件,我们需要以下约束条件:

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

现在,假设我们想让一个视图占据屏幕的一半,但是我们没有另一半的视图。我们仍然可以使用自动布局来实现,但是设置略有不同。在这个例子中,我们的视图是蓝色的,其父视图是绿色的。

步骤1:

enter image description here

这与上面的步骤1类似,只是我们不添加右侧约束(如果我们想占用不同的一半,则会有所不同)。

步骤2:

enter image description here

与之前一样,我们要分配“等宽”约束。在这种情况下,从我们的视图到父视图。再次按住控件键并从一个拖动到另一个。

enter image description here

此时,我们有一个自动布局警告。自动布局希望我们的框架与其父母的宽度相匹配。单击警告并选择“更新约束”将放置硬编码值。我们不想要这个。

步骤3:

enter image description here

选择视图并转到其大小检查器。在这里,我们将能够编辑约束。

单击“Equal Width to:”约束旁边的“Edit”。我们需要更改乘数值。

enter image description here

我们需要将乘数值更改为2。

约束现在变为“Proportional Width to:”,所有自动布局警告和错误都消失了。现在我们的视图将始终占据超级视图的一半。

要在代码中添加这些约束,我们可以使用VFL添加一些:

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

但是比例宽度约束不能使用VFL添加。我们必须像这样添加:

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

非常棒的答案,我喜欢你付出的努力。既然我知道了等宽度,你能告诉我如何以编程方式设置吗?这个会起作用吗?@"[leftView][rightView][leftView(==rightView)]" - NYC Tech Engineer
使用VFL设置等宽约束非常简单,只需@"[leftView(==rightView)]"。但您还需要其他约束条件。因此,您需要:@"|[leftView(==rightView)][rightView]|"(仍然需要垂直约束)。 - nhgrif
(也请记住您可以更改接受答案。) - nhgrif
太好了,我正在寻找第二种情况。但有一件事对我不起作用。我必须将乘数设置为0.5而不是2。IB一直希望我的半视图的宽度是父视图宽度的两倍。更改为0.5后,我得到了预期的结果。 - Michael Peterson
非常好的解决方案,我正在使用“乘数”== 2来实现我的请求。谢谢。 - Kevin
显示剩余3条评论

7
在XIB或Storyboard中创建一个UIView
1.设置顶部和左侧约束 2.设置高度约束 3.将宽度约束设置为与父视图的宽度相等 *重要* 4.通过将其转换为十进制来编辑约束的宽度

enter image description here

  1. 将小数点设置为所需宽度(例如我的情况是0.5或一半)

Result


4

在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


    }

}

4

将它们都绑定到父视图边缘(表格视图绑定到前沿,网页视图绑定到后沿),并设置它们具有相同的宽度约束。


1
您还需要在表视图和网页视图之间添加水平间距约束。 - rdelmar
所以,现在在竖屏模式下,它们的宽度都为384。只需给它们两个都设置一个当前值的宽度约束? - NYC Tech Engineer
1
不。选择它们并创建一个约束,该约束将说“等宽度”。正如@rdelmar所提到的那样-确保在表视图的右边缘和Web视图的左边缘之间有约束。 - sha
1
我认为两个视图之间存在水平间距约束,并且我也设置了它们的宽度约束。但在横向模式下,表格视图占据了屏幕的三分之二。 - NYC Tech Engineer
1
移除任何指定硬编码宽度的约束。 - sha

0
约束系统无法读取你的思想,你必须清楚地表达你的需求。一半就是一半,如果你想要一半,就应该说出来。如果想让一个视图的宽度是其父视图的一半,需要给它一个宽度约束,并设置一个乘数为.5与其父视图的宽度相关联。

9
你可以省略前四句话,最后一句话才是实际提供有用信息的地方。我会将其翻译为:您本可以省略前四个句子,最后一个句子是您实际提供有用信息的地方。 - Michael Peterson
很酷,谢谢。我会使用这个有用的信息。"给它一个宽度约束,其乘数相对于其父视图的宽度为0.5。" - Edward Chiang
是的,这是一个很好的答案...正是我在寻找的。只可惜有点傲慢的语气。 - barrylachapelle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接