How to lock orientation just for one view controller?

佐手、 提交于 2019-12-08 05:04:28

问题


Can I set a portrait orientation and lock orientation just in one controller?

I did try:

override func supportedInterfaceOrientations() -> Int {
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

override func shouldAutorotate() -> Bool{
    return false
}

but it doesn't help me. Must I to add anything else?


回答1:


This code should work:

    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.Portrait.rawValue)
    }

    override func shouldAutorotate() -> Bool{
        return false
    }

    override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
        return UIInterfaceOrientation.Portrait
    }

If it is now working for you, then I suppose your controller is in some another controller(UINavigationController, UITabBarController, UISplitViewController). In this case you need to use this code in that parent controller.

If your navigation controller contain more than one view controller, and you need to disable orientation only for some of them, then you need to inherit UINavigationController class and write there something like:

class NavigationController: UINavigationController {

    var shouldRotate: Bool = true

    override func supportedInterfaceOrientations() -> Int {
        return shouldRotate ? Int(UIInterfaceOrientationMask.Portrait.rawValue) : Int(UIInterfaceOrientationMask.All.rawValue)
    }

    override func shouldAutorotate() -> Bool{
        return shouldRotate
    }
}

Then in controller that you need to disable orientation you can disable it for your navigation controller:

class ViewController: UIViewController {

    var lastControllerRotationStatus: Bool?

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        if let navigationController = self.navigationController as? NavigationController {
            lastControllerRotationStatus = navigationController.shouldRotate
            navigationController.shouldRotate = false
        }
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)

        if let navigationController = self.navigationController as? NavigationController {
            navigationController.shouldRotate = lastControllerRotationStatus ?? true
        }
    }
}

But remember, that you need to restore old rotation status after your controller will be pushed out navigation controller. In this example I'm saving rotation status before changing it, and restoring it after controller disappeared. Also you can use some other approach. For example you can overload UINavigationController method popViewController, and there set shouldRotate to false.

The same approach with variable setting from controller you can use for controlling rotation from AppDelegate method application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int

Then you do not need to inherit from navigation controller.

Your AppDelegate class code will look like:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    var shouldRotate = true
    func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {

        return shouldRotate ? Int(UIInterfaceOrientationMask.All.rawValue) : Int(UIInterfaceOrientationMask.Portrait.rawValue)

    }

}

And your controller code will look like:

class ViewController: UIViewController {

    var lastControllerRotationStatus: Bool?

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
            lastControllerRotationStatus = appDelegate.shouldRotate
            appDelegate.shouldRotate = false
        }
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)

        if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
            appDelegate.shouldRotate = lastControllerRotationStatus ?? true
        }
    }
}



回答2:


If you want Portrait orientation but you want to lock only one viewController (for example in landscape) you can do it in this way:

This worked for me with Swift 2.0

AppDelegate

var shouldRotate = true

//MARK: - Func to rotate only one view controller
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {

    if (shouldRotate == true){
        return UIInterfaceOrientationMask.All
    }

    return UIInterfaceOrientationMask.Landscape

}

ViewController

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1. lock the rotation
        let appdelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appdelegate.shouldRotate = false

        // 2. Force the device in landscape mode when the view controller gets loaded
        UIDevice.currentDevice().setValue(UIInterfaceOrientation.LandscapeRight.rawValue, forKey: "orientation")
    }

    override func shouldAutorotate() -> Bool {
        // 3. Lock autorotate
        return false
    }

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return [UIInterfaceOrientationMask.LandscapeRight, UIInterfaceOrientationMask.LandscapeLeft]
    }


    override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {

        // 4. Only allow Landscape
        return UIInterfaceOrientation.LandscapeRight
    }

    // 5. Restoring the locked-rotation before controller disappeared
    override func viewWillDisappear(animated: Bool) {
        let appdelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appdelegate.shouldRotate = true
    }



回答3:


I found this on a similar question. Link

"First of all, I really thank you to zellb who give me this answer and make me understand.In order to set device orientation for one view controller to portrait and others to both,you can set this at AppDelegate.swift with this function that had supportedInterfaceOrientationsForWindow

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int {

return checkOrientation(self.window?.rootViewController?)// This is the custom function that u need to set your custom view to each orientation which u want to lock

}

And here is the function which check for each view controller to set Portrait or All Orientation base on what u want.

func checkOrientation(viewController:UIViewController?)-> Int{

if(viewController == nil){

    return Int(UIInterfaceOrientationMask.All.rawValue)//All means all orientation

}else if (viewController is SignInViewController){

    return Int(UIInterfaceOrientationMask.Portrait.rawValue)//This is sign in view controller that i only want to set this to portrait mode only

}else{

    return checkOrientation(viewController!.presentedViewController?)
}
}

and dont forget to set the view controller which u want to lock at Attribute Inspector which include orientation to "Portrait" and others to "Inferred""

Hope that helps.




回答4:


**Add to your AppDelegate file:*

var orientationLock = UIInterfaceOrientationMask.all
  func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return self.orientationLock
  }

  struct AppUtility {
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
      if let delegate = UIApplication.shared.delegate as? AppDelegate {
        delegate.orientationLock = orientation
      }
    }

    static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
      self.lockOrientation(orientation)
      UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
    }
  }

Add to the viewcontroller that you want to force an orientation:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    AppDelegate.AppUtility.lockOrientation(.portrait)
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    AppDelegate.AppUtility.lockOrientation(.all)
  }



回答5:


Just put this in viewDidAppear:

let value = UIInterfaceOrientation.Portrait.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")



回答6:


Swift 3 Answer:

In the view controller you want to lock the orientation of

override var shouldAutorotate: Bool {
    return false
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .portrait
}

override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .portrait
}

Adapted from how to lock portrait orientation for only main view using swift



来源:https://stackoverflow.com/questions/29950456/how-to-lock-orientation-just-for-one-view-controller

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