ios 以编程方式使用自动布局的宽度和高度等于其超级视图?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18756640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:08:12  来源:igfitidea点击:

Width and Height Equal to its superView using autolayout programmatically?

iosswiftdynamicautolayoutnslayoutconstraint

提问by Bordz

I've been looking for a lot of snippets in the net and I still can't find the answer to my problem. My question is I have a scrollView(SV) and I want to add a button inside scrollView(SV) programmatically with same width and height of its superview which is scrollView(SV) so that when user rotate the device button will have the same frame of scrollView(SV). how to do the NSLayout/NSLayoutConstraint? thanks

我一直在网上寻找很多片段,但仍然找不到问题的答案。我的问题是我有一个 scrollView(SV) 并且我想以编程方式在 scrollView(SV) 内添加一个按钮,其超级视图的宽度和高度与 scrollView(SV) 相同,这样当用户旋转设备按钮时,按钮将具有相同的框架滚动视图(SV)。如何做 NSLayout/NSLayoutConstraint?谢谢

采纳答案by Bordz

I'm not sure if this is the most efficient way to do it, but it works..

我不确定这是否是最有效的方法,但它有效..

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = NO;
// initialize


[coverForScrolView addSubview:button];

NSLayoutConstraint *width =[NSLayoutConstraint
                                    constraintWithItem:button
                                    attribute:NSLayoutAttributeWidth
                                    relatedBy:0
                                    toItem:coverForScrolView
                                    attribute:NSLayoutAttributeWidth
                                    multiplier:1.0
                                    constant:0];
NSLayoutConstraint *height =[NSLayoutConstraint
                                     constraintWithItem:button
                                     attribute:NSLayoutAttributeHeight
                                     relatedBy:0
                                     toItem:coverForScrolView
                                     attribute:NSLayoutAttributeHeight
                                     multiplier:1.0
                                     constant:0];
NSLayoutConstraint *top = [NSLayoutConstraint
                                   constraintWithItem:button
                                   attribute:NSLayoutAttributeTop
                                   relatedBy:NSLayoutRelationEqual
                                   toItem:coverForScrolView
                                   attribute:NSLayoutAttributeTop
                                   multiplier:1.0f
                                   constant:0.f];
NSLayoutConstraint *leading = [NSLayoutConstraint
                                       constraintWithItem:button
                                       attribute:NSLayoutAttributeLeading
                                       relatedBy:NSLayoutRelationEqual
                                       toItem:coverForScrolView
                                       attribute:NSLayoutAttributeLeading
                                       multiplier:1.0f
                                       constant:0.f];
[coverForScrolView addConstraint:width];
[coverForScrolView addConstraint:height];
[coverForScrolView addConstraint:top];
[coverForScrolView addConstraint:leading];

回答by MadNik

If someone is looking for a Swift solution– I would create a Swift extension for UIViewwhich will help you each time you want to bind a subviews frame to its superviews bounds:

如果有人正在寻找Swift 解决方案——我会创建一个 Swift扩展,UIView每次你想将子视图框架绑定到它的超级视图边界时它都会帮助你:

Swift 2:

斯威夫特 2:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }

}

Swift 3:

斯威夫特 3:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }
}

Swift 4.2:

斯威夫特 4.2:

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        self.topAnchor.constraint(equalTo: superview.topAnchor, constant: 0).isActive = true
        self.bottomAnchor.constraint(equalTo: superview.bottomAnchor, constant: 0).isActive = true
        self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 0).isActive = true
        self.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: 0).isActive = true

    }
}

Then simply call it like this:

然后简单地这样称呼它

// after adding as a subview, e.g. `view.addSubview(subview)`
subview.bindFrameToSuperviewBounds()

回答by uniruddh

This link can help you,follow the instructions : http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

此链接可以帮助您,请按照说明操作:http: //www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

EDIT :

编辑 :

use following code snippet, where subview is your subivew.

使用以下代码片段,其中 subview 是您的 subivew。

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(subview)]];
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-0-[subview]-0-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(subview)]];

回答by beryllium

addConstraintand removeConstraintmethods for UIView are going to be deprecated, so it's worth to use 'constraint creation conveniences':

addConstraintremoveConstraintUIView 的方法和方法将被弃用,因此值得使用“约束创建便利”:

view.topAnchor.constraint(equalTo: superView.topAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: superView.bottomAnchor, constant: 0).isActive = true
view.leadingAnchor.constraint(equalTo: superView.leadingAnchor, constant: 0).isActive = true
view.trailingAnchor.constraint(equalTo: superView.trailingAnchor, constant: 0).isActive = true

回答by Jeehut

Approach #1: Via UIView Extension

方法一:通过 UIView 扩展

Here's a more functionalapproach in Swift 3+with a preconditioninstead of a print(which can perish easily in the console). This one will report programmer errorsas failed builds.

这是Swift 3+ 中一种更实用的方法,它带有一个先决条件而不是 a (它很容易在控制台中消失)。这将报告程序员错误作为失败的构建。print

Add this extensionto your project:

将此扩展添加到您的项目中:

extension UIView {
    /// Adds constraints to the superview so that this view has same size and position.
    /// Note: This fails the build if the `superview` is `nil` – add it as a subview before calling this.
    func bindEdgesToSuperview() {
        guard let superview = superview else {
            preconditionFailure("`superview` was nil – call `addSubview(view: UIView)` before calling `bindEdgesToSuperview()` to fix this.")
        }
        translatesAutoresizingMaskIntoConstraints = false
        ["H:|-0-[subview]-0-|", "V:|-0-[subview]-0-|"].forEach { visualFormat in
            superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: visualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        }
    }
}

Now simply call itlike this:

现在简单地这样称呼它

// after adding as a subview, e.g. `view.addSubview(subview)`
subview.bindEdgesToSuperview()

Note that the above method is already integratedinto my HandyUIKitframework which also adds some more handy UI helpers into your project.

请注意,上述方法已经集成到我的HandyUIKit框架中,它还向您的项目中添加了一些更方便的 UI 助手。



Approach #2: Using a Framework

方法#2:使用框架

If you work a lot with programmatic constraintsin your project then I recommend you to checkout SnapKit. It makes working with constraints a lot easierand less error-prone.

如果您在项目中经常使用编程约束,那么我建议您查看SnapKit。它使处理约束变得更容易,也更不容易出错

Follow the installation instructionsin the docs to include SnapKit into your project. Then importit at the top of your Swift file:

按照文档中的安装说明将 SnapKit 包含到您的项目中。然后在 Swift 文件的顶部导入它:

import SnapKit

Now you can achieve the same thing with just this:

现在您可以通过以下方式实现相同的目的:

subview.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

回答by PLJNS

Swift 3:

斯威夫特 3:

import UIKit

extension UIView {

    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }

}

回答by Masih

Swift 4using NSLayoutConstraint:

Swift 4使用NSLayoutConstraint

footerBoardImageView.translatesAutoresizingMaskIntoConstraints = false
let widthConstraint  = NSLayoutConstraint(item: yourview, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: superview, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0)
let heightConstraint = NSLayoutConstraint(item: yourview, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: superview, attribute: NSLayoutAttribute.height, multiplier: 1, constant: 0)
superview.addConstraints([widthConstraint, heightConstraint])

回答by Matt Pinkston

As a supplemental answer, and one for those not opposed to including third party libraries, the PureLayoutlibrary provides a method to do just this. Once the library is installed, it's as simple as

作为一个补充答案,对于那些不反对包含第三方库的人来说,PureLayout库提供了一种方法来做到这一点。安装库后,就像这样简单

myView.autoPinEdgesToSuperviewEdges()

There are other libraries which can provide similar functionality as well depending on taste, eg. Masonry, Cartography.

还有其他库也可以根据口味提供类似的功能,例如。砌体制图

回答by James Larcombe

As a follow up to @Dschee's solution, here is swift 3.0 syntax: (Please note: this is not my solution, I have just fixed it for Swift 3.0)

作为@Dschee 解决方案的后续,这里是 swift 3.0 语法:(请注意:这不是我的解决方案,我刚刚为 Swift 3.0 修复了它)

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
}

回答by Jonny

I needed to cover the superview completely. The other ones wouldn't do that during orientation changes. So I wrote a new one which does - using an arbitrary size multiplier of 20. Feel free to change to your needs. Also note this one in fact makes the subview a lot bigger than the superview which might be different from requirements.

我需要完全覆盖超级视图。其他人不会在方向改变期间这样做。所以我写了一个新的 - 使用 20 的任意大小乘数。随意更改您的需要。还要注意这个实际上使子视图比父视图大很多,这可能与需求不同。

extension UIView {
    func coverSuperview() {
        guard let superview = self.superview else {
            assert(false, "Error! `superview` was nil – call `addSubview(_ view: UIView)` before calling `\(#function)` to fix this.")
            return
        }
        self.translatesAutoresizingMaskIntoConstraints = false
        let multiplier = CGFloat(20.0)
        NSLayoutConstraint.activate([
            self.heightAnchor.constraint(equalTo: superview.heightAnchor, multiplier: multiplier),
            self.widthAnchor.constraint(equalTo: superview.widthAnchor, multiplier: multiplier),
            self.centerXAnchor.constraint(equalTo: superview.centerXAnchor),
            self.centerYAnchor.constraint(equalTo: superview.centerYAnchor),
            ])
    }
}