Change anchor constraints based on device orientation

Hi.


I would like to add an UIView in my SKScene with three components in it: a UILabel, a UITextField, and a UIButton. Their layout must change based on the device orientation. In the Landscape mode, they will all be aligned along the Y-axis; in the Portrait mode, they will be located one under another aligned along the X-axis. The height of the view must also change accordingly.


For now, I am trying to change the size of the UIView based on the orientation like this:


        let newView = UIView()
        newView.backgroundColor = UIColor.red
        newView.translatesAutoresizingMaskIntoConstraints = false
        self.view?.addSubview(newView)
       
        let newViewLeftAnchorLandscape = newView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20)
        let newViewRightAnchorLandscape = newView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20)
        let newViewTopAnchorLandscape = newView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20)
        let newViewHeightAnchorLandscape = newView.heightAnchor.constraint(equalToConstant: 40)
        let newViewHeightAnchorPortrait = newView.heightAnchor.constraint(equalToConstant: 150)
       
        if UIDevice.current.orientation.isLandscape
        {
            newViewLeftAnchorLandscape.isActive = true
            newViewRightAnchorLandscape.isActive = true
            newViewTopAnchorLandscape.isActive = true
            newViewHeightAnchorLandscape.isActive = true
            newViewHeightAnchorPortrait.isActive = false
        }
        else
        {
            newViewLeftAnchorLandscape.isActive = true
            newViewRightAnchorLandscape.isActive = true
            newViewTopAnchorLandscape.isActive = true
            newViewHeightAnchorLandscape.isActive = false
            newViewHeightAnchorPortrait.isActive = true
        }


However, in either orientation the height of the view is 150.


Making newViewHeightAnchor a class property and then implementing like this:


        if UIDevice.current.orientation.isLandscape
        {
            newViewLeftAnchorLandscape.isActive = true
            newViewRightAnchorLandscape.isActive = true
            newViewTopAnchorLandscape.isActive = true
            newViewHeightAnchor = newView.heightAnchor.constraint(equalToConstant: 30)
            newViewHeightAnchor.isActive = true
        }
        else
        {
            newViewLeftAnchorLandscape.isActive = true
            newViewRightAnchorLandscape.isActive = true
            newViewTopAnchorLandscape.isActive = true
            newViewHeightAnchor = newView.heightAnchor.constraint(equalToConstant: 150)
            newViewHeightAnchor.isActive = true
        }


helps when opening the scene. However, it does not resize the view when changing the orientation here:


    overridefunc didChangeSize(_ oldSize: CGSize)
    {
        if newView != nil
        {
            if UIDevice.current.orientation.isLandscape
            {
                newViewHeightAnchor = newView.heightAnchor.constraint(equalToConstant: 30)
                newViewHeightAnchor.isActive = true
            }
            else
            {
                newViewHeightAnchor = newView.heightAnchor.constraint(equalToConstant: 150)
                newViewHeightAnchor.isActive = true
            }
        }
    }


Any thoughts?


Thanks a lot!

Replies

You should try making the change in viewWillLayoutSubviews


    override func viewWillLayoutSubviews() {
      
        super.viewWillLayoutSubviews()  // 5.9.2018
        // Let us adapt some constraints in portrait mode
        if newView != nil 
        { 
            if UIDevice.current.orientation.isLandscape 
            { 
                newViewHeightAnchor = newView.heightAnchor.constraint(equalToConstant: 30) 
                newViewHeightAnchor.isActive = true 
            } 
            else 
            { 
                newViewHeightAnchor = newView.heightAnchor.constraint(equalToConstant: 150) 
                newViewHeightAnchor.isActive = true 
            } 
        } 

    }

Claude31. My class is a subclass of SKScene. There is no method


viewWillLayoutSubviews()



to override. Appreciated, anyways.


Any other ideas?


Thank you.

I'm not very familiar with SceneKit.


did you try call

scene.view.setNeedsLayout()

in didChangeSize


There is also an update func. But probably not much use here


func update(_ currentTime: TimeInterval)