Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITextField is not filing available width inside UIStackView

I want to put two buttons with images on left and right edges of the screen, and insert a UITextField between them. In storyboard everything is fine, but I need to do it programmatically.

Source:

class SecondViewController: UIViewController {


override func loadView() {
    super.loadView()
    self.view.backgroundColor = .white
    let leftButton = UIButton()
    leftButton.setImage(UIImage(named: "first"), for: .normal)
    leftButton.setTitle("", for: .normal)
    
    let rightButton = UIButton()
    rightButton.setImage(UIImage(named: "second"), for: .normal)
    rightButton.setTitle("", for: .normal)
    
    let textField = UITextField()
    textField.placeholder = "clear"
    textField.borderStyle = .roundedRect
    textField.contentHorizontalAlignment = .left
    textField.contentVerticalAlignment = .center
    
    let stackView = UIStackView()
    
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.alignment = .fill
    stackView.distribution = .fill
    stackView.axis = .horizontal
    stackView.spacing = 15

    stackView.addArrangedSubview(leftButton)
    stackView.addArrangedSubview(textField)
    stackView.addArrangedSubview(rightButton)
    
    self.view.addSubview(stackView)
    
    NSLayoutConstraint(item: stackView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 15).isActive = true
    NSLayoutConstraint(item: stackView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1.0, constant: -15).isActive = true
    NSLayoutConstraint(item: stackView, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1.0, constant: 50).isActive = true
    
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
}

I need a result like on first image.

I need result like this

But at result, I have second. but got this

What did I do wrong ?

like image 970
FezZ Avatar asked Mar 04 '23 20:03

FezZ


2 Answers

You have an elementary constraint ambiguity. You could easily have discovered this just by switching to the View Debugger; you would see three exclamation marks warning you of the problem. The layout engine does not magically know which of the three views should be allowed to stretch horizontally. You have to tell it:

textField.setContentHuggingPriority(UILayoutPriority(249), for: .horizontal)
like image 50
matt Avatar answered Mar 06 '23 22:03

matt


Set constraints like

NSLayoutConstraint.activate([
    stackView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50),
    stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 15),
    stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -15),
    stackView.heightAnchor.constraint(equalToConstant: 45),
    leftButton.widthAnchor.constraint(equalToConstant: 30), 
    rightButton.widthAnchor.constraint(equalToConstant: 30),
])

Another small change

rightButton.imageView?.contentMode = .scaleAspectFit
leftButton.imageView?.contentMode = .scaleAspectFit

Result

enter image description here

like image 25
Sh_Khan Avatar answered Mar 06 '23 21:03

Sh_Khan