如何以编程方式创建带有约束的视图

Posted

技术标签:

【中文标题】如何以编程方式创建带有约束的视图【英文标题】:How to create this view with constraints programtically 【发布时间】:2020-06-11 21:45:21 【问题描述】:

我觉得这很容易完成,但我似乎无法弄清楚。对于不使用情节提要并尝试学习如何以编程方式为我的视图设置约束,我还很陌生。我在情节提要中轻松创建了我想要的视图,但似乎无法以编程方式获得它。

我有我的视图控制器有我的父视图,然后我调用一个容器视图。我想在容器视图中是我设置约束的地方,但每次更改到不同的设备时,我都无法让视图的高度保持不变

class ViewController: UIViewController 
override func viewDidLoad() 
    super.viewDidLoad()
    var clariView = ClariContainerView()
    view.addSubview(clariView)

这是我的视图控制器,然后我的 ClariContainerView 如下所示:

class ClariContainerView: UIView 

lazy var clariQuestionView: UIView = 
    let containerView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 0))
    containerView.backgroundColor = .blue
    containerView.translatesAutoresizingMaskIntoConstraints = false
    return containerView
()

override init(frame: CGRect) 
    super.init(frame: frame)
    setupView()



required init?(coder: NSCoder) 
    super.init(coder: coder)
    setupView()


public func setupView() 
    addSubview(clariQuestionView)
    setupLayout()


public func setupLayout() 
    NSLayoutConstraint.activate([
        clariQuestionView.heightAnchor.constraint(equalToConstant: 169)
    ])

我要重新创建的是:

我需要蓝色视图的高度始终为 169。

【问题讨论】:

我建议你使用 Interface Builder 和 Autolayout - 它们更容易使用,而且信息更难在代码中丢失。 我希望可以,但我的工作是尽量避免使用故事板和 xibs 【参考方案1】:

你可以这样做:

首先,您不需要为您的 containerView 定义框架,因为 translatesAutoresizingMaskIntoConstraints = falsestatement 指定您将使用自动布局,因此框架将被忽略:
    lazy var clariQuestionView: UIView = 
        let containerView = UIView()
        containerView.backgroundColor = .blue
        containerView.translatesAutoresizingMaskIntoConstraints = false
        return containerView
    ()
下面是定义约束的方法。您需要设置高度,还需要将视图固定到 self.view 的底部、前缘和后缘:
    public func setupLayout() 
        NSLayoutConstraint.activate([
            clariQuestionView.heightAnchor.constraint(equalToConstant: 169),
            clariQuestionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
            clariQuestionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
            clariQuestionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
        ])
    

【讨论】:

【参考方案2】:

对于这样的基本布局,您实际上不需要添加heightAnchor。这是实现所需行为 + 奖励的简单方法 — 根据设备的 safeAreaInsets 调整高度的代码 sn-p。

class ClariContainerView: UIView 
    lazy var clariQuestionView: UIView = 
        let desiredContainerHeigh = 169
        // If you want, you can use commented code to adjust height according to the device's safe area.
        // This might be needed if you want to keep the same height over safe area on all devices.
        // let safeAreaAdjustment = UIApplication.shared.keyWindow?.rootViewController?.view.safeAreaInsets.bottom ?? 0
        let containerView = UIView(frame: CGRect(x: 0, y: UIScreen.main.bounds.height - 169, width: UIScreen.main.bounds.width, height: 169))
        containerView.backgroundColor = .blue
        containerView.translatesAutoresizingMaskIntoConstraints = true
        return containerView
    ()

    override init(frame: CGRect) 
        super.init(frame: frame)
        setupView()
    

    required init?(coder: NSCoder) 
        super.init(coder: coder)
        setupView()
    

    public func setupView() 
        addSubview(clariQuestionView)
    

【讨论】:

以上是关于如何以编程方式创建带有约束的视图的主要内容,如果未能解决你的问题,请参考以下文章

iOS:以编程方式添加约束获取视图高度作为唯一指标

为啥我以编程方式创建的视图会忽略其约束?

如何向放置在 UIStackView 中的以编程方式创建的 UIButton 添加约束

如何在 ios swift 中以编程方式创建自动布局等宽约束?

如果使用自动布局以编程方式创建 UIView 会延迟显示

以编程方式创建的 rootviewcontroller 未显示分配的 viewcontroller 的内容