Change Viewcontroller based on device orientation in iOS 8/9

拜拜、爱过 提交于 2019-12-12 05:32:24

问题


What is the preferred way of segueying between two viewcontrollers based on device orientation in iOS 8/9? I want to build an instrument that is shown in landscape. In portrait i want to show the settings of the App.


回答1:


In AppDelegate.swift inside the "didFinishLaunchingWithOptions" function I put:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "rotated", name: UIDeviceOrientationDidChangeNotification, object: nil)

And then inside the AppDelegate class, put the following function:

func rotated(){
    if(UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation){            
        println("landscape")
    }

    if(UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)){
        println("Portrait")
    }
}

Or you can use this:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.currentDevice().orientation.isLandscape.boolValue {
        println("landscape")
    } else {
        println("portraight")
    }
}



回答2:


Here is my mechanism I created for iOS 9, but this should also work for iOS 8 as well.

import UIKit

extension CGSize {

    static func minMaxSize(size: CGSize) -> CGSize {

        return CGSize(width: size.minValue(), height: size.maxValue())
    }

    static func maxMinSize(size: CGSize) -> CGSize {

        return CGSize(width: size.maxValue(), height: size.minValue())
    }

    func minValue() -> CGFloat {

        return min(self.width, self.height)
    }

    func maxValue() -> CGFloat {

        return max(self.width, self.height)
    }
}

extension UIScreen {

    func isPortrait() -> Bool {

        return self.bounds.width < self.bounds.height
    }
}

class BaseViewController: UIViewController {

    var horizontalConstraints = [NSLayoutConstraint]()
    var verticalConstraints = [NSLayoutConstraint]()

    private lazy var _isPortrait: Bool = UIScreen.mainScreen().isPortrait()

    func isPortrait() -> Bool {

        if let parentViewController = self.parentViewController as? BaseViewController {

            return parentViewController.isPortrait()
        }

        return _isPortrait
    }

    override func loadView() {

        self.view = UIView()
    }

    override func viewDidLoad() {

        super.viewDidLoad()

        self.addViewController()

        self.addLayoutGuides()
        self.setupLayoutGuides()

        self.addSubViews()
        self.setupSubViews()
    }

    func addViewController() {

        /* override point */
    }

    func addLayoutGuides() {

        /* override point */
    }

    func setupLayoutGuides() {

        /* override point */
    }

    func addSubViews() {

        /* override point */
    }

    func setupSubViews() {

        /* override point */
    }

    private func applyConstraints() {

        self.willApplyConstraints()

        self.isPortrait() ? self.applyVerticalConstrains() : self.applyHorizontalConstrains()

        self.didApllyedConstraints()
    }

    func willApplyConstraints() {

        /* override point */
    }

    func applyVerticalConstrains() {

        /* override point */
    }

    func applyHorizontalConstrains() {

        /* override point */
    }

    func didApllyedConstraints() {

        /* override point */


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

        if let superView = self.view.superview {

            if superView.isKindOfClass(UIWindow.self) && self.parentViewController == nil {

                if CGSize.minMaxSize(size) == CGSize.minMaxSize(UIScreen.mainScreen().bounds.size) {

                    _isPortrait = size.width < size.height
                }
            }
        }

        super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

        self.applyConstraints()
    }
}

At least I assume that the child viewController will never touch inherited private _isPortrait, because it is lazy. Only the top level view can of the rootViewController is allowed to set this property. The super viewWillTransitionToSize function is called after the check is done. So if the value was set on the rootViewController, all child viewController will have the correct value at the time their viewWillTransitionToSize function is called. This has to be done, because you can not rely on the the size of the child viewController views, but at least you can trust your `rootViewController if it is fullscreen. Hope that will help someone somehow.

So my RootViewController may look like this now.

class RootViewController: BaseViewController {

    override func addViewController() {

        /* add child view controller here so they can receive callbacks */
    }

    override func addSubViews() {

        /* add your subviews here in a way you like so you can play with AutoLayout as you wish */
    }

    override func setupSubViews() {

        /* setup up your views here and always activate vertical constraints here */
        /* because iOS will always initialize in portrait even if launched in landscape */
        /* deactivate your horizontal constrains and put them inside the array */
        /* add vertical constraints to the vertical array; other constraints can be active */
        /* without the need to be added somewhere */
    }

    override func willApplyConstraints() {

        /* deactivate all constrains */
        NSLayoutConstraint.deactivateConstraints(self.verticalConstraints)
        NSLayoutConstraint.deactivateConstraints(self.horizontalConstraints)
    }

    override func applyVerticalConstrains() {

        NSLayoutConstraint.activateConstraints(self.verticalConstraints)
    }

    override func applyHorizontalConstrains() {

        NSLayoutConstraint.activateConstraints(self.horizontalConstraints)
    }

    override func didApllyedConstraints() {

        /* force layouting if needed */
        self.view.layoutIfNeeded()
    }
}

UPDATE (Xcode 7 - OS X 10.11.1 beta): For iPad testing use iPad 2 or iPad Retina simulator, because the Air 1/2 are broken with AutoLayout. All simulators will produce this message: <CATransformLayer: 0x790af320> - changing property masksToBounds in transform-only layer, will have no effect



来源:https://stackoverflow.com/questions/31460049/change-viewcontroller-based-on-device-orientation-in-ios-8-9

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!