RjC
RjC

Reputation: 827

How to set constraint relationship to view, not subviews programmatically?

I am trying to setup a couple of views programmatically. On my main view I add two subviews, one anchored to the top and one to the bottom:

//Button View
        view.addSubview(buttonsLabel)
        buttonsLabel.translatesAutoresizingMaskIntoConstraints = false

        buttonsLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        buttonsLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        buttonsLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true

        buttonsLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5, constant: -20).isActive = true


//Calculator View
        calcLabel.layer.cornerRadius = 25
        view.addSubview(calcLabel)

        calcLabel.translatesAutoresizingMaskIntoConstraints = false

        calcLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        calcLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        calcLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 40).isActive = true
        //calcLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true

        calcLabel.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5, constant: -40).isActive = true

This works fine, both views are 50% of the frame height (minus the constants) and both are shown (one at the top, one at the bottom). But when I try to add a third view, which is 75% of the frames height and which should be placed on top of the other two views, the layout is destroyed and everything is moved almost outside of the frame.

I am trying to anchor the third view to the bottom again:

    thirdView.layer.cornerRadius = 25
    view.addSubview(thirdView)

    thirdView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    thirdView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    thirdView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    thirdView.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.75).isActive = true

This is how everything should look like (left the two views, right the third view on top:

enter image description here

Am I doing the anchors and constraints right (or whats abetter way) and how to add the constraint for the third view, so that it is 75% of the frames height and placed like in the image on top of everything.

Upvotes: 2

Views: 1805

Answers (1)

RLoniello
RLoniello

Reputation: 2329

Your code looks good the problem is else where, check the view hierarchy in the debugger to see which constraint(s) failed, perhaps you forgot translatesAutoresizingMaskIntoConstraints as beyowulf commented. you should be using constants as well, this makes code much more maintainable.

here is my implementation:

import UIKit

class ViewController: UIViewController {


    //MARK: - SubViews
    let topHalfView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor.gray
        return view
    }()

    let bottomHalfView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor.gray
        return view
    }()

    let threeQuarterView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor.black
        return view
    }()




    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        //add, layout subviews with 9+ constraints
        setupViews()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func setupViews() {
        self.view.addSubview(topHalfView)
        self.view.addSubview(bottomHalfView)
        self.view.addSubview(threeQuarterView)

        let guide = self.view.safeAreaLayoutGuide
        let spacing:CGFloat = 12
        let viewHeight = self.view.frame.height - spacing


        topHalfView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
        topHalfView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: spacing).isActive = true
        topHalfView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -spacing).isActive = true
        topHalfView.heightAnchor.constraint(equalToConstant: viewHeight * 0.5).isActive = true

        bottomHalfView.topAnchor.constraint(equalTo: topHalfView.bottomAnchor, constant: spacing).isActive = true
        bottomHalfView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: spacing).isActive = true
        bottomHalfView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -spacing).isActive = true
        bottomHalfView.heightAnchor.constraint(equalToConstant: viewHeight * 0.5).isActive = true

        threeQuarterView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
        threeQuarterView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: spacing).isActive = true
        threeQuarterView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -spacing).isActive = true
        threeQuarterView.heightAnchor.constraint(equalToConstant: self.view.frame.height * 0.75).isActive = true
    }

}

The View hierarchy:

The View hierarchy

Upvotes: 3

Related Questions