Search code examples
swiftuibuttonautolayoutuitextfieldnslayoutconstraint

Constraining Text Field to Button in Swift


I have a button I created in my storyboard, but have a custom UITextField that needs to be implemented in code, I am trying to place the text field so that it's 20 pixels above the button, but I am not getting the desired result for some reason. Am I missing something or is this not how you implement it? here's my implementation and output:

@IBOutlet weak var buyPointsButton: UIButton!

lazy var cardTextField: STPPaymentCardTextField = {
    let cardTextField = STPPaymentCardTextField()
    return cardTextField
}()

In viewDidLoad

self.view.addSubview(cardTextField)
cardTextField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    NSLayoutConstraint(item: cardTextField, attribute: .bottom, relatedBy: .equal, toItem: buyPointsButton, attribute: .top, multiplier: 1, constant: 70),
    NSLayoutConstraint(item: cardTextField, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: buyPointsButton.frame.width),
    NSLayoutConstraint(item: cardTextField, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: 0),
    NSLayoutConstraint(item: cardTextField, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 28)
])

enter image description here

enter image description here


Solution

  • The main problem is that you are setting the text field's .centerY to the view's .centerY and you're constraining the Bottom of the text field to the Top of the button...

    You'll find it much easier to work with constraints if you use the more "modern" syntax, and include comments telling yourself what the constraints are - or at least, should be - doing.

    For example:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        self.view.addSubview(cardTextField)
        cardTextField.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            
            // Bottom of text field 20-points above Top of button
            cardTextField.bottomAnchor.constraint(equalTo: buyPointsButton.topAnchor, constant: -20.0),
            
            // text field Width equal to button Width
            cardTextField.widthAnchor.constraint(equalTo: buyPointsButton.widthAnchor),
            
            // text field centered horizontally to button
            cardTextField.centerXAnchor.constraint(equalTo: buyPointsButton.centerXAnchor),
            
            // text field Height equal to 28
            cardTextField.heightAnchor.constraint(equalToConstant: 28.0),
            
        ])
    }