Search code examples
iosswiftautolayout

Swift 4 NSLayoutConstraint not works properly


have a problem with NSLayoutConstraint and .scaleAspectFill after applying logoView (positioning and scaling) and titleLabel constraints, titleLabel's Y position not sets correctly

titleLabel.topAnchor.constraint(equalTo: logoView.bottomAnchor, constant: 20])

here my sample:

let logoView:UIImageView = {
        let img = UIImage(named: "big_logo")
        let im = UIImageView(image: img)
        im.translatesAutoresizingMaskIntoConstraints = false
        im.contentMode = .scaleAspectFill
        return im
}()

    lazy var titleLabel:UILabel = {
        let title:UILabel = UILabel()
        title.translatesAutoresizingMaskIntoConstraints = false
        title.text = MuiPack.getMuiString(key: "splash_greeting")
        title.font = UIFont.boldSystemFont(ofSize: 18)
        title.textColor = .black
        return title
    }()

 NSLayoutConstraint.activate([logoView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.6),
                                     logoView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
                                     logoView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: -20)])

NSLayoutConstraint.activate([titleLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
                                     titleLabel.topAnchor.constraint(equalTo: logoView.bottomAnchor, constant: 20])

Solution

  • Your logoView does not have an intrinsicSize, so it has no height.

    If you change your initialization as follows, you'll see what's happening:

    let logoView:UIImageView = {
        let img = UIImage(named: "cross")
        let im = UIImageView(image: img)
        im.translatesAutoresizingMaskIntoConstraints = false
        im.contentMode = .scaleAspectFill
        // set a background color so you can see the image view's frame
        im.backgroundColor = .blue
        // clip the image to the bounds of the view's frame
        im.clipsToBounds = true
        return im
    }()
    

    You can either set an explicit height constraint, or set it proportional to its width.

    This will make it "square":

        NSLayoutConstraint.activate([
            logoView.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.6),
            logoView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),            
            logoView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: -20),
            // add proportional height anchor
            logoView.heightAnchor.constraint(equalTo: logoView.widthAnchor, multiplier: 1.0)
            ])