Swift - How to detect orientation changes

后端 未结 13 1818
余生分开走
余生分开走 2020-11-29 19:49

I want to add two images to single image view (i.e for landscape one image and for portrait another image)but i don\'t know how to detect orientation changes using swift lan

13条回答
  •  再見小時候
    2020-11-29 20:29

    ⚠️Device Orientation != Interface Orientation⚠️

    Swift 5.* iOS14 and below

    You should really make a difference between:

    • Device Orientation => Indicates the orientation of the physical device
    • Interface Orientation => Indicates the orientation of the interface displayed on the screen

    There are many scenarios where those 2 values are mismatching such as:

    • When you lock your screen orientation
    • When you have your device flat

    In most cases you would want to use the interface orientation and you can get it via the window:

    private var windowInterfaceOrientation: UIInterfaceOrientation? {
        return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
    }
    

    In case you also want to support < iOS 13 (such as iOS 12) you would do the following:

    private var windowInterfaceOrientation: UIInterfaceOrientation? {
        if #available(iOS 13.0, *) {
            return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
        } else {
            return UIApplication.shared.statusBarOrientation
        }
    }
    

    Now you need to define where to react to the window interface orientation change. There are multiple ways to do that but the optimal solution is to do it within willTransition(to newCollection: UITraitCollection.

    This inherited UIViewController method which can be overridden will be trigger every time the interface orientation will be change. Consequently you can do all your modifications in the latter.

    Here is a solution example:

    class ViewController: UIViewController {
        override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
            super.willTransition(to: newCollection, with: coordinator)
            
            coordinator.animate(alongsideTransition: { (context) in
                guard let windowInterfaceOrientation = self.windowInterfaceOrientation else { return }
                
                if windowInterfaceOrientation.isLandscape {
                    // activate landscape changes
                } else {
                    // activate portrait changes
                }
            })
        }
        
        private var windowInterfaceOrientation: UIInterfaceOrientation? {
            return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
        }
    }
    

    By implementing this method you'll then be able to react to any change of orientation to your interface. But keep in mind that it won't be triggered at the opening of the app so you will also have to manually update your interface in viewWillAppear().

    I've created a sample project which underlines the difference between device orientation and interface orientation. Additionally it will help you to understand the different behavior depending on which lifecycle step you decide to update your UI.

    Feel free to clone and run the following repository: https://github.com/wjosset/ReactToOrientation

提交回复
热议问题