ajrlewis
ajrlewis

Reputation: 3058

Updating autolayout constraints depending on orientation

I have a ViewController class that has a textField variable, which is configured when it is set in the viewDidLoad method of the ViewController.

class ViewController: UIViewController {

    weak var textField: UITextField! {
        didSet {
            textField.delegate = self
            textField.placeholder = "Enter Text"
            view.addSubview(textField)
            view.addConstraint(NSLayoutConstraint(item: textField, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 0.80, constant: 0))
            view.addConstraint(NSLayoutConstraint(item: textField, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 0.05, constant: 0))
            view.addConstraint(NSLayoutConstraint(item: textField, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0))
            view.addConstraint(NSLayoutConstraint(item: textField, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0))
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        textField = UITextField()
    }
}

A set of auto layout constraints are added to the view. I want this text field be centered in the middle (.CenterX and .CenterY), to be 80% (5%) the width (height) of the ViewController's view calculated in portrait mode.

If the device's orientation (UIDevice.currentDevice().orientation) is rotated into landscape orientation, or presented from a landscape orientation, I want the width (height) to remain the same as that for portrait orientation.

Changing the attribute for the toItem in:

view.addConstraint(NSLayoutConstraint(item: textField, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 0.05, constant: 0))

to:

attribute: (UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation) ? .Height : .Width)

Doesn't do the trick as I guess the textField isn't getting (re)set when the device switches orientation. Furthermore, this check seems a bit clumpy for Swift. Am I missing a trick with autolayout?

Upvotes: 0

Views: 1197

Answers (2)

keshav vishwkarma
keshav vishwkarma

Reputation: 1852

Actually the problem in your code is that you did not set the translatesAutoresizingMaskIntoConstraints of textField to false, whenever you want to use auto-layout constraints then you have to set translatesAutoresizingMaskIntoConstraints of a view to false.

I have updated your code have a look and its working fine.

class ViewController: UIViewController, UITextFieldDelegate {    
    weak var textField: UITextField! {
        didSet {
            textField.delegate = self
            textField.placeholder = "Enter Text"
            view.addSubview(textField)
            // to see the size of textField
            textField.backgroundColor = UIColor.purpleColor()

            textField.translatesAutoresizingMaskIntoConstraints = false

            view.addConstraint(NSLayoutConstraint(item: textField, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 0.80, constant: 0))
            view.addConstraint(NSLayoutConstraint(item: textField, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 0.05, constant: 0))
            view.addConstraint(NSLayoutConstraint(item: textField, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0))
            view.addConstraint(NSLayoutConstraint(item: textField, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0))
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        textField = UITextField()

    }
}

Upvotes: 2

stakri
stakri

Reputation: 1397

One solution would be to get the fixed coordinate bounds of the screen (iOS >= 8) and adjust the first two constraints appropriately:

class ViewController: UIViewController, UITextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let textField = UITextField()
        textField.translatesAutoresizingMaskIntoConstraints = false
        textField.delegate = self
        textField.placeholder = "Enter Text"
        view.addSubview(textField)

        textField.backgroundColor = UIColor.redColor()
        textField.textAlignment = .Center

        let fixedScreenBounds = UIScreen.mainScreen().fixedCoordinateSpace.bounds

        NSLayoutConstraint.activateConstraints([
            NSLayoutConstraint(item: textField, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 0, constant: 0.8*fixedScreenBounds.width),
            NSLayoutConstraint(item: textField, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 0, constant: 0.05*fixedScreenBounds.height),
            NSLayoutConstraint(item: textField, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: textField, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0)
            ])
    }
}

Also, be aware that, since you are creating the textfield in code and you want to use autolayout, you must set its translatesAutoresizingMaskIntoConstraints to false.

Upvotes: 0

Related Questions