slysid slysid - 3 years ago 240
Swift Question

Adding Constraint using VFL - iOS Swift

I am getting myself introduced to VFL and I am trying out something which I need some help.

I have the image view aligned like in below image in portrait mode.
enter image description here

In landscape the view looks as below

enter image description here

In landscape I want the image to be centered along Y-Axis i.e and little bit up than shown in the image.

I have the below VFL code

override func viewDidLoad() {

googleSignButton = UIImageView()
googleSignButton!.translatesAutoresizingMaskIntoConstraints = false
googleSignButton!.image = UIImage(named: "google.png")
self.view!.addSubview(googleSignButton!)

let buttonWidth:CGFloat = 50
let views:[String:UIImageView] = Dictionary(dictionaryLiteral: ("google",googleSignButton!))
let metrics = ["dim" : buttonWidth,
"horizontalPadding" : (UIScreen.mainScreen().bounds.width - (3 * buttonWidth)) / 3,
"verticalPadding" : (UIScreen.mainScreen().bounds.height * 0.5) - (buttonWidth * 0.5)]

let horizontalConstraint = NSLayoutConstraint.constraintsWithVisualFormat("H:|-horizontalPadding-[google(dim)]", options:[] , metrics: metrics, views: views)
let verticalConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:|-verticalPadding-[google(dim)]", options:[] , metrics: metrics, views: views)
self.view.addConstraints(verticalConstraint)
self.view.addConstraints(horizontalConstraint)
}


How can I achieve that. Potrait mode looks fine and in landscape, the image has to be centered vertically.

Thank you.

Edit

Updated Code:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in



}) { (UIViewControllerTransitionCoordinatorContext) -> Void in

self.calculateConstraints()

}
}

func calculateConstraints() {

let buttonWidth:CGFloat = Common.sharedCommon.calculateDimensionForDevice(50)

let views:[String:UIImageView] = Dictionary(dictionaryLiteral: ("google",googleSignButton!))
let metrics = ["dim" : 50.0,
"horizontalPadding" : (UIScreen.mainScreen().bounds.width - (3 * buttonWidth)) / 3,
"verticalPadding" : (UIScreen.mainScreen().bounds.height * 0.5) - (buttonWidth * 0.5)]


if let horizontal = horizontalConstraint, let vertical = verticalConstraint {

NSLayoutConstraint.deactivateConstraints([horizontal])
NSLayoutConstraint.deactivateConstraints([vertical])
}

horizontalConstraint = NSLayoutConstraint.constraintsWithVisualFormat("H:|-horizontalPadding-[google(dim)]", options:[] , metrics: metrics, views: views)[0]
verticalConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:|-verticalPadding-[google(dim)]", options:[] , metrics: metrics, views: views)[0]

NSLayoutConstraint.activateConstraints([horizontalConstraint!,verticalConstraint!])

}


Images:
enter image description here

enter image description here

Answer Source

So your problem is that the constraints don't get updated on rotation, so it is using the same vertical constraint for landscape.

First, you'll actually want to save your constraints in properties for deactivation purposes. In your view controller:

var verticalConstraints: [NSLayoutConstraint]?
var horizontalConstraints: [NSLayoutConstraint]?

Then, wrap your constraint code in a function (note I modified it slightly):

function calculateButtonConstraints() {
    let buttonWidth:CGFloat = 50
    let views:[String:UIImageView] = Dictionary(dictionaryLiteral: ("google",googleSignButton!))
    let metrics = ["dim" : buttonWidth,
                   "horizontalPadding" : (UIScreen.mainScreen().bounds.width - (3 * buttonWidth)) / 3,
        "verticalPadding" : (UIScreen.mainScreen().bounds.height * 0.5) - (buttonWidth * 0.5)]

    if let horizontal = horizontalConstraints, let vertical = verticalConstraints {
        NSLayoutConstraint.deactivateConstraints(horizontal)
        NSLayoutConstraint.deactivateConstraints(vertical)
    }

    horizontalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|-horizontalPadding-[google(dim)]", options:[] , metrics: metrics, views: views)
    verticalConstraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|-verticalPadding-[google(dim)]", options:[] , metrics: metrics, views: views)

    NSLayoutConstraint.activateConstraints(horizontalConstraints!)
    NSLayoutConstraint.activateConstraints(verticalConstraints!)
}

Note that I used NSLayoutConstraint.activateConstraints: instead, as that is the preferred way. Also, that is in part with deactivateConstraints:.

Then, instead of that code in viewDidLoad:, put this:

calculateButtonConstraints()

Next, add this to your view controller:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    coordinator.animateAlongsideTransition(nil, completion: { [unowned self]
        self.calculateButtonConstraints()
    })

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download