问题
I'm creating my UI programmatically and I want to make my UITextfield topAnchor to be based off the height of its containing UIView but it's not working.
My UITextfield is inside a UIView and I want its topAnchor to be 0.15 the height of the UIView as such - containerView.frame.size.height * 0.15 but it seems the value is not picking up. All this is done in a UIView subclass and called in the ViewController
let containerView: UIView
containerView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(containerView)
NSLayoutConstraint.activate([
containerView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
containerView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.9),
containerView.topAnchor.constraint(equalTo: stepTitleLabel.bottomAnchor, constant: 50),
containerView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.65)
])
let userTextField: UITextField
userTextField?.tag = 1
userTextField?.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(userTextField)
userTextField.setNeedsLayout()
print("containerView.frame.size.height * 0.15:\(containerView.frame.size.height * 0.15)")
NSLayoutConstraint.activate([
(userTextField.centerXAnchor.constraint(equalTo: containerView.centerXAnchor))!,
(userTextField.widthAnchor.constraint(equalTo: containerView.widthAnchor, multiplier: 0.8))!,
userTextField.topAnchor.constraint(equalTo: containerView.topAnchor, constant: containerView.frame.size.height * 0.15),
userTextField.heightAnchor.constraint(equalToConstant: 40)
])
I expect the topAnchor of my UITextField to appear similar across all devices at 0.15 the height of it container view but what I'm getting is 0
回答1:
Don't mix NSLayoutConstraints and frames. The frames are static and don't update when you use them for the constant in a constraint. So when Auto Layout uses the other constraints to update the height of containerView, your constraint that looks at containerView's frame height will be based upon the height of the containerView at the time of the constraint's creation (which is likely 0) and not at the time Auto Layout uses the constraints to establish the height of containerView.
Instead, you want to base the top of userTextField on the bottom of containerView with a multiplier. Unfortunately, you can't do that with layout anchors, and you'll have to use NSLayoutContraint to create it:
Replace:
userTextField.topAnchor.constraint(equalTo: containerView.topAnchor,
constant: containerView.frame.size.height * 0.15)
with:
NSLayoutConstraint(item: userTextField, attribute: .top, relatedBy: .equal,
toItem: containerView, attribute: .bottom, multiplier: 0.15, constant: 0)
回答2:
You need to make it with self not container as container's height is not yet calculated
userTextField.topAnchor.constraint(equalTo: containerView.topAnchor,
constant: self.frame.size.height * 0.15 * 0.65 )
Given that the height of container = 0.65 * from self here
self.heightAnchor, multiplier: 0.65
来源:https://stackoverflow.com/questions/56020632/layout-constraints-not-working-with-view-frame-size-height