宽度和高度是否以编程方式使用autolayout等于superView?

时间:2013-09-12 06:13:20

标签: ios swift dynamic autolayout nslayoutconstraint

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

11 个答案:

答案 0 :(得分:107)

如果有人正在寻找 Swift解决方案 - 我会为UIView 创建一个Swift 扩展程序,它会在您每次要绑定子视图时为您提供帮助框架到其超级视图边界:

斯威夫特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]))
    }

}

斯威夫特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:

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

    }
}

然后只需将其称为

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

答案 1 :(得分:68)

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

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

答案 2 :(得分:46)

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

编辑:

使用以下代码段,其中子视图是您的子视图。

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

答案 3 :(得分:16)

UIView的

addConstraintremoveConstraint方法将被弃用,因此值得使用'约束创建便利':

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

答案 4 :(得分:7)

方法#1:通过UIView扩展

这是 Swift 3 + 中的更多功能性方法,带有前置条件而不是print(可以轻易地消亡控制台)。这个将报告程序员错误作为失败的构建。

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

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]))
        }
    }
}

现在简单地称之为,就像这样:

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

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

方法#2:使用框架

如果您在项目中大量使用程序化约束,那么我建议您结帐SnapKit。它使得约束很多更容易更不容易出错

按照文档中的 installation instructions 将SnapKit包含到您的项目中。然后在Swift文件的顶部导入

import SnapKit

现在你可以用这个来实现同样的目的:

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

答案 5 :(得分:6)

斯威夫特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]))
    }

}

答案 6 :(得分:2)

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

答案 7 :(得分:1)

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

一样简单
myView.autoPinEdgesToSuperviewEdges()

还有其他库可以根据口味提供类似的功能,例如。 MasonryCartography

答案 8 :(得分:1)

我从其他答案中选择了最好的元素:

import webbrowser
import pyautogui
import time
# Open Website
webbrowser.open('https://www.midomi.com/index.php?action=m\
ain.track&track_id=100712805442046374&from=voice_search')
# Have it record audio
time.sleep(5)
pyautogui.click(659, 99)

您可以像在自定义UIView中那样使用它:

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

    NSLayoutConstraint.activate([
      self.topAnchor.constraint(equalTo: superview.topAnchor),
      self.bottomAnchor.constraint(equalTo: superview.bottomAnchor),
      self.leadingAnchor.constraint(equalTo: superview.leadingAnchor),
      self.trailingAnchor.constraint(equalTo: superview.trailingAnchor)
    ])
  }
}

答案 9 :(得分: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]))
}

答案 10 :(得分:0)

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

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),
            ])
    }
}