UIView frame does not update after orientation change

How to detect a change in orientation after it happened with Swift 3?

I need to detect it after the change in order to calculate the frame size.

EDIT

I asked this question because I need to redraw the idea of ​​a change in orientation, as in this question: I can’t get a background gradient to fill the entire screen when rotating

I do not know how to implement the answer marked as the correct answer.

I tried a different answer

self.backgroundImageView.layer.sublayers?.first?.frame = self.view.bounds

but it does not work.

In viewDidLoad()i have

let color1 =  UIColor(red: 225.0/255.0, green: 210.0/255.0, blue: 0.0/255.0, alpha: 1.0).cgColor
let color2 = UIColor(red: 255.0/255.0, green: 125.0/255.0, blue: 77.0/255.0, alpha: 1.0).cgColor

let gradientLayer = CAGradientLayer()
gradientLayer.colors = [color1, color2]
gradientLayer.locations = [ 0.0, 1.0]
gradientLayer.frame = self.view.bounds

self.view.layer.insertSublayer(gradientLayer, at: 0)
+8
source share
7 answers

. , . .

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

        coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in

            let orient = UIApplication.shared.statusBarOrientation

            switch orient {

            case .portrait:

                print("Portrait")

            case .landscapeLeft,.landscapeRight :

                print("Landscape")

            default:

                print("Anything But Portrait")
            }

            }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
                //refresh view once rotation is completed not in will transition as it returns incorrect frame size.Refresh here           

        })
        super.viewWillTransition(to: size, with: coordinator)

    }
+24

, :

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else if UIDevice.current.orientation.isPortrait {
        print("Portrait")
    }
}
+6

,

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

func rotated() {
    if(UIDeviceOrientationIsLandscape(UIDevice.current.orientation))
    {
        print("landscape")
    }

    if(UIDeviceOrientationIsPortrait(UIDevice.current.orientation))
    {
        print("Portrait")
    }
}
+6

, :

(1) , , , . ( , , ...?)

(2) , .

(3) My application also has an extension for editing photos, so UIApplication was not available. (In addition, orientations such as landscapeLeft and landscapeRight do not work in this type of extension.)

NOTE. I add my structure for AutoLayout for completeness.

UIViewController:

var p = [NSLayoutConstraint]()
var l = [NSLayoutConstraint]()
var initialOrientation = true
var isInPortrait = false

override func viewDidLoad() {
    super.viewDidLoad()
    // set up all constraints, including common, portrait and landscape
    setUpConstraints()  
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    if initialOrientation {
        initialOrientation = false
        if view.frame.width > view.frame.height {
            isInPortrait = false
        } else {
            isInPortrait = true
        }
        orientationChanged()
    } else {
        if view.orientationHasChanged(&isInPortrait) {
            orientationChanged()
        }
    }
}

func orientationChanged() {
    // this was split out because of other app-specific logic
    view.setOrientation(p, l)
}

UIView:

extension UIView {

    public func orientationHasChanged(_ isInPortrait:inout Bool) -> Bool {
        // always check against isInPortrait to reduce unnecessary AutoLayout changes!
        if self.frame.width > self.frame.height {
            if isInPortrait {
                isInPortrait = false
                return true
            }
        } else {
            if !isInPortrait {
                isInPortrait = true
                return true
            }
        }
        return false
    }
    public func setOrientation(_ p:[NSLayoutConstraint], _ l:[NSLayoutConstraint]) {
        NSLayoutConstraint.deactivate(l)
        NSLayoutConstraint.deactivate(p)
        if self.bounds.width > self.bounds.height {
            NSLayoutConstraint.activate(l)
        } else {
            NSLayoutConstraint.activate(p)
        }
    }
}
+3
source

try it

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {

        print("Landscape mode called")

        if UI_USER_INTERFACE_IDIOM() == .Pad {
            print("Landscape mode in ipad");

        }
        else
        {
            print("Landscape mode in Iphone ")

        }
    } else {
        print("Portrait mode called")
        if UI_USER_INTERFACE_IDIOM() == .Pad {

            print("Portrait mode called in ipad")
        }
        else
        {
            print("Portrait mode called in iphone")
        }
    }
}
override func willRotateToInterfaceOrientation(toInterfaceOrientation:UIInterfaceOrientation, duration: NSTimeInterval) {
    print("willRotateToInterfaceOrientation method called");
    //Here you can invalidateLayout()
}
0
source
override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {

    self.sliding.setNeedsDisplay()

}
0
source

If you use this to get the updated traitCollection value, use this instead

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    print("Trait collection changes")

}
0
source

Source: https://habr.com/ru/post/1658934/


All Articles