skip to Main Content

I’ve created a UIView, which has buttons in it. I set the constraints like this :

NSLayoutConstraint.activate([
    sampleView.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 20),
    sampleView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
    sampleView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
])

Not added any height or bottom anchor as I want it to be dynamic in height.
Initially sampleView has no buttons, so it doesn’t appear in UI. I then add buttons in it vertical to each other and it works fine.

The problem I’m facing right now is, there is another view(tempView) just below this sampleView. And initially I set tempView’s topAnchor to sampleView’s bottomAnchor.
So it is placed properly on screen initially.

When I add buttons in sampleView, it expands, but tempView don’t. I tried with view.layoutIfNeeded() and setting the topAnchor with new height of sampleView but nothing works out for me.

Please help me with this.

2

Answers


  1. You must do something to give sampleView a Height.

    One easy way is to add a vertical UIStackView as a subview of sampleView, constrain all 4 sides to sampleView, and then add buttons as arranged subviews of the stack view.

    Quick example:

    class ExampleVC: UIViewController {
        
        let topView = UIView()
        let sampleView = UIView()
        let tempView = UIView()
        
        // let's use a vertical stack view to hold the buttons inside sampleView
        let stackView = UIStackView()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .systemBackground
            
            [topView, sampleView, tempView].forEach { v in
                v.translatesAutoresizingMaskIntoConstraints = false
                view.addSubview(v)
            }
            
            topView.backgroundColor = .yellow
            sampleView.backgroundColor = .green
            tempView.backgroundColor = .cyan
            
            let g = view.safeAreaLayoutGuide
            NSLayoutConstraint.activate([
                
                topView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
                topView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
                topView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
                topView.heightAnchor.constraint(equalToConstant: 100.0),
                
                sampleView.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 20.0),
                sampleView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
                sampleView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
                // sampleView has no Height constraint ...
                //  we're adding a stack view to it, and as we add buttons to the stack view
                //  it will control the Height
                
                tempView.topAnchor.constraint(equalTo: sampleView.bottomAnchor, constant: 20.0),
                tempView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
                tempView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0),
                tempView.heightAnchor.constraint(equalToConstant: 100.0),
                
            ])
            
            // stackView to hold the buttons
            stackView.axis = .vertical
            stackView.spacing = 8
            
            stackView.translatesAutoresizingMaskIntoConstraints = false
            sampleView.addSubview(stackView)
            
            NSLayoutConstraint.activate([
                
                // constrain all 4 sides of the stack view to sampleView
                stackView.topAnchor.constraint(equalTo: sampleView.topAnchor, constant: 0.0),
                stackView.leadingAnchor.constraint(equalTo: sampleView.leadingAnchor, constant: 0.0),
                stackView.trailingAnchor.constraint(equalTo: sampleView.trailingAnchor, constant: 0.0),
                stackView.bottomAnchor.constraint(equalTo: sampleView.bottomAnchor, constant: 0.0),
                
            ])
        }
        
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            let btnNumber = stackView.arrangedSubviews.count + 1
            let btn = UIButton()
            btn.backgroundColor = .red
            btn.setTitle("Button (btnNumber)", for: [])
            stackView.addArrangedSubview(btn)
        }
        
    }
    

    At start, because we haven’t added any buttons to the stack view, it will look like this:

    enter image description here

    Tap anywhere to add buttons — here is what we get after the first tap:

    enter image description here

    and after a couple more taps:

    enter image description here

    Login or Signup to reply.
  2. class ViewController: UIViewController {
    
    ///Variable
    var viewA: UIView!
    
    ///View lifecycle functions
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Do any additional setup after loading the view.
        
        viewA = UIView()
        viewA.translatesAutoresizingMaskIntoConstraints = false
        viewA.backgroundColor = .red
        view.addSubview(viewA)
        
        let viewB = UIView()
        viewB.translatesAutoresizingMaskIntoConstraints = false
        viewB.backgroundColor = .green
        view.addSubview(viewB)
        
        
        
        NSLayoutConstraint.activate([
            viewA.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
            viewA.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            viewA.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            
            viewB.topAnchor.constraint(equalTo: viewA.bottomAnchor, constant: 20),
            viewB.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            viewB.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            viewB.heightAnchor.constraint(equalToConstant: 50),
            
            
        ])
        viewA.layoutIfNeeded()
        
        setupSubview()
    }
    override func viewDidLayoutSubviews() {
        view.layoutIfNeeded()
    }
    func setupSubview(){
        DispatchQueue.main.asyncAfter(deadline: .now() + 5 ) {
            let viewSub = UIView()
            viewSub.translatesAutoresizingMaskIntoConstraints = false
            viewSub.backgroundColor = .purple
            self.viewA.addSubview(viewSub)
            
            NSLayoutConstraint.activate([
               
                viewSub.topAnchor.constraint(equalTo: self.viewA.topAnchor, constant: 20),
                viewSub.leadingAnchor.constraint(equalTo: self.viewA.leadingAnchor, constant: 16),
                viewSub.trailingAnchor.constraint(equalTo: self.viewA.trailingAnchor, constant: -16),
                viewSub.heightAnchor.constraint(equalToConstant: 60),
                viewSub.bottomAnchor.constraint(equalTo: self.viewA.bottomAnchor)
              
            ])
            
            self.viewA.layoutIfNeeded()
            print(self.viewA.frame)
        }
    }
    

    }

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search