在Swift中,以编程方式创建UIView并向其添加控件并使用自动布局,使控件显示在视图的父级上

时间:2017-11-30 00:52:17

标签: ios swift autolayout storyboard

我正在尝试在Swift 3中为iOS编写一个简单的复合组件。它由一个UILabel后跟一个水平布局的UITextField,后面跟着一行。但是,UILabel消失了,UITextField出现在父视图上,行也消失了。

My design in sketch

What it actually looks like in the Storyboard

My component's constraints in the view controller

我的目的是使用自动布局,将标签锚定到视图的顶部和前导锚点,将文本字段锚定到视图的顶部,并使用常量将标签的尾部锚点固定,这样它们就会并排出现。 / p>

我确实对此进行了大量研究,一个看起来非常接近我想要的网站https://www.raywenderlich.com/125718/coding-auto-layout,我认为我或多或少采用了相同的方法。

我做的事情显然是错误的,但无法弄清楚是什么。非常感谢任何帮助,我已经在这几天了。

import UIKit

@IBDesignable
class OTextEdit: UIView {

    @IBInspectable var LabelText: String = "Label"
    @IBInspectable var SecureText: Bool = false
    @IBInspectable var Color: UIColor = UIColor.black
    @IBInspectable var Text: String = "" {
        didSet {
            edit.text = Text
        }
    }

    fileprivate let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 35))
    fileprivate let edit = UITextField(frame: CGRect(x: 210, y: 0, width: 200, height: 35))
    fileprivate let line: UIView = UIView()

    override var intrinsicContentSize: CGSize {
        return CGSize(width: 300, height: 100)
    }

    func setup() {
        label.text = LabelText
        label.textColor = Color
        label.font = UIFont(name: "Avenir Next Condensed", size: 24)
        edit.font = UIFont(name: "Avenir Next Condensed", size: 24)
        edit.borderStyle = .roundedRect
        edit.isSecureTextEntry = SecureText
        line.backgroundColor = UIColor.white

        self.addSubview(label)
        self.addSubview(edit)
        self.addSubview(line)
    }

    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        setup()
        setupConstaints()
    }

    func setupConstaints() {
        label.translatesAutoresizingMaskIntoConstraints = false
        edit.translatesAutoresizingMaskIntoConstraints = false
        line.translatesAutoresizingMaskIntoConstraints = false
        label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: -10).isActive = true
        label.topAnchor.constraint(equalTo: topAnchor)
        edit.leadingAnchor.constraint(equalTo: label.leadingAnchor, constant: 10).isActive = true
        edit.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true
        edit.topAnchor.constraint(equalTo: self.topAnchor)
        line.heightAnchor.constraint(equalToConstant: 2.0).isActive = true
        line.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10).isActive = true
        line.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true
        line.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 1.0).isActive = true
    }
}

1 个答案:

答案 0 :(得分:1)

您没有从上到下的一系列约束,因此自动布局无法确定对象的内容大小。您已尝试通过initrinsicContentSize进行设置,但您不需要这样做。

您还需要为标签设置水平拥抱优先级,让自动布局知道您希望文本字段展开:

我删除了您对intrinsicContentSize的覆盖,并将约束更改为:

  • 将标签的底部限制在该行的顶部
  • 将线条底部限制在超级视图的底部
  • 将标签的基线约束到文本字段的基线
  • 删除文本字段顶部和超级视图之间的约束
  • 设置标签的水平拥抱优先级。

 func setupConstraints() {
    label.translatesAutoresizingMaskIntoConstraints = false
    edit.translatesAutoresizingMaskIntoConstraints = false
    line.translatesAutoresizingMaskIntoConstraints = false

    label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10).isActive = true
    label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
    label.topAnchor.constraint(equalTo: topAnchor)
    label.bottomAnchor.constraint(equalTo: line.topAnchor, constant: -8).isActive = true

    edit.leadingAnchor.constraint(equalTo: label.trailingAnchor, constant: 10).isActive = true
    edit.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true
    edit.firstBaselineAnchor.constraint(equalTo: label.firstBaselineAnchor).isActive = true

    line.heightAnchor.constraint(equalToConstant: 2.0).isActive = true
    line.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10).isActive = true
    line.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true
    line.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 1.0).isActive = true
    line.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}

我认为这与你所追求的非常接近。