如何在Swift中将一个视图控制器的方向locking到肖像模式
由于我的应用程序得到所有方向的支持。 我想只locking肖像模式到特定的UIViewController。
(例如,假设它是选项卡式应用程序,当SignIn View以模态方式出现时,我只希望将SignIn View视为纵向模式,无论用户如何旋转设备或当前设备的方向如何)
如果有复杂的视图层次结构(如具有多个导航控制器和/或选项卡视图控制器),事情会变得非常混乱。
这个实现把它放在每个视图控制器上,以便当他们想要locking方向时,而不是依靠App Delegate来通过迭代子视图来find它们。
Swift 3
在AppDelegate中:
/// set orientations you want to be allowed in this property by default var orientationLock = UIInterfaceOrientationMask.all func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return self.orientationLock }
在其他一些全局结构体或帮助器类中,我在这里创build了AppUtility:
struct AppUtility { static func lockOrientation(_ orientation: UIInterfaceOrientationMask) { if let delegate = UIApplication.shared.delegate as? AppDelegate { delegate.orientationLock = orientation } } /// OPTIONAL Added method to adjust lock and rotate to the desired orientation static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) { self.lockOrientation(orientation) UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation") } }
然后在所需的ViewController中,您要locking方向:
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) AppUtility.lockOrientation(.portrait) // Or to rotate and lock // AppUtility.lockOrientation(.portrait, andRotateTo: .portrait) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Don't forget to reset when view is being removed AppUtility.lockOrientation(.all) }
如果iPad或通用应用程序
确保在“目标设置” – >“常规” – >“部署信息”中选中“需要全屏”。 supportedInterfaceOrientationsFor
代表将不会被调用,如果没有选中。
添加此代码强制肖像并locking它:
override func viewDidLoad() { super.viewDidLoad() // Force the device in portrait mode when the view controller gets loaded UIDevice.currentDevice().setValue(UIInterfaceOrientation.Portrait.rawValue, forKey: "orientation") } override func shouldAutorotate() -> Bool { // Lock autorotate return false } override func supportedInterfaceOrientations() -> Int { // Only allow Portrait return Int(UIInterfaceOrientationMask.Portrait.rawValue) } override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation { // Only allow Portrait return UIInterfaceOrientation.Portrait }
在您的AppDelegate中 – 将supportedInterfaceOrientationsForWindow设置为您希望整个应用程序支持的任何方向:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask { return UIInterfaceOrientationMask.All }
要将横向方向设置为应用的所有视图,并且只允许所有方向的一个视图(例如,可以添加相机胶卷):
在AppDelegate.swift中:
var adaptOrientation = false
在:didFinishLaunchingWithOptions
NSNotificationCenter.defaultCenter().addObserver(self, selector: "adaptOrientationAction:", name:"adaptOrientationAction", object: nil)
在AppDelegate.swift的其他地方:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int { return checkOrientation(self.window?.rootViewController) } func checkOrientation(viewController:UIViewController?)-> Int{ if (adaptOrientation == false){ return Int(UIInterfaceOrientationMask.Landscape.rawValue) }else { return Int(UIInterfaceOrientationMask.All.rawValue) } } func adaptOrientationAction(notification: NSNotification){ if adaptOrientation == false { adaptOrientation = true }else { adaptOrientation = false } }
然后在这个视图中,继续你想要的所有方向:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { if (segue.identifier == "YOURSEGUE") { NSNotificationCenter.defaultCenter().postNotificationName("adaptOrientationAction", object: nil) } } override func viewWillAppear(animated: Bool) { if adaptOrientation == true { NSNotificationCenter.defaultCenter().postNotificationName("adaptOrientationAction", object: nil) } }
最后一件事是打勾设备方向: – 肖像 – 左侧景观 – 右侧景观
在这个线程中有一堆很好的答案,但没有一个比较符合我的需求。 我有一个标签的应用程序与每个选项卡中的导航控制器,一个视图需要旋转,而其他需要被locking在肖像。 导航控制器没有正确调整它的子视图,出于某种原因。 结合这个答案find了一个解决scheme(在Swift 3中),布局问题消失了。 按照@bmjohns的build议创build结构体:
import UIKit struct OrientationLock { static func lock(to orientation: UIInterfaceOrientationMask) { if let delegate = UIApplication.shared.delegate as? AppDelegate { delegate.orientationLock = orientation } } static func lock(to orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation: UIInterfaceOrientation) { self.lock(to: orientation) UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation") } }
然后子类UITabBarController:
import UIKit class TabBarController: UITabBarController, UITabBarControllerDelegate { required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.delegate = self } func tabBarControllerSupportedInterfaceOrientations(_ tabBarController: UITabBarController) -> UIInterfaceOrientationMask { if tabBarController.selectedViewController is MyViewControllerNotInANavigationControllerThatShouldRotate { return .allButUpsideDown } else if let navController = tabBarController.selectedViewController as? UINavigationController, navController.topViewController is MyViewControllerInANavControllerThatShouldRotate { return .allButUpsideDown } else { //Lock view that should not be able to rotate return .portrait } } func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { if viewController is MyViewControllerNotInANavigationControllerThatShouldRotate { OrientationLock.lock(to: .allButUpsideDown) } else if let navController = viewController as? UINavigationController, navController.topViewController is MyViewControllerInANavigationControllerThatShouldRotate { OrientationLock.lock(to: .allButUpsideDown) } else { //Lock orientation and rotate to desired orientation OrientationLock.lock(to: .portrait, andRotateTo: .portrait) } return true } }
不要忘记将故事板中的TabBarController的类更改为新创build的子类。
这是您的问题和其他相关问题的通用解决scheme。
1.创build辅助类UIHelper并使用以下方法:
/**This method returns top view controller in application */ class func topViewController() -> UIViewController? { let helper = UIHelper() return helper.topViewControllerWithRootViewController(rootViewController: UIApplication.shared.keyWindow?.rootViewController) } /**This is a recursive method to select the top View Controller in a app, either with TabBarController or not */ private func topViewControllerWithRootViewController(rootViewController:UIViewController?) -> UIViewController? { if(rootViewController != nil) { // UITabBarController if let tabBarController = rootViewController as? UITabBarController, let selectedViewController = tabBarController.selectedViewController { return self.topViewControllerWithRootViewController(rootViewController: selectedViewController) } // UINavigationController if let navigationController = rootViewController as? UINavigationController ,let visibleViewController = navigationController.visibleViewController { return self.topViewControllerWithRootViewController(rootViewController: visibleViewController) } if ((rootViewController!.presentedViewController) != nil) { let presentedViewController = rootViewController!.presentedViewController; return self.topViewControllerWithRootViewController(rootViewController: presentedViewController!); }else { return rootViewController } } return nil }
2.创build一个与你的愿望行为的协议,为您的具体情况将肖像。
协议orientationIsOnlyPortrait {}
注意:如果你想要的话,把它添加到UIHelper类的顶部。
3.扩展您的视图控制器
在你的情况下:
class Any_ViewController: UIViewController,orientationIsOnlyPortrait { .... }
4.在应用程序委托类中添加此方法:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { let presentedViewController = UIHelper.topViewController() if presentedViewController is orientationIsOnlyPortrait { return .portrait } return .all }
最后说明:
- 如果你有更多的class级在肖像模式,只要扩展该协议。
- 如果你想从视图控制器的其他行为,创build其他协议,并遵循相同的结构。
- 这个例子解决推视图控制器后方向改变的问题
bmjohns – >你是我的救世主。 这是唯一的工作解决scheme(使用AppUtility结构)
我创build了这个类:
class Helper{ struct AppUtility { static func lockOrientation(_ orientation: UIInterfaceOrientationMask) { if let delegate = UIApplication.shared.delegate as? AppDelegate { delegate.orientationLock = orientation } } /// OPTIONAL Added method to adjust lock and rotate to the desired orientation static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) { self.lockOrientation(orientation) UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation") } } }
并按照你的指示,一切工作完美的Swift 3 – > Xcode版本8.2.1
感谢上面的@ bmjohn的回答。 这是一个工作Xamarin / C#版本的答案的代码,以节省其他人的转录时间:
AppDelegate.cs
public UIInterfaceOrientationMask OrientationLock = UIInterfaceOrientationMask.All; public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow) { return this.OrientationLock; }
Static OrientationUtility.cs类:
public static class OrientationUtility { public static void LockOrientation(UIInterfaceOrientationMask orientation) { var appdelegate = (AppDelegate) UIApplication.SharedApplication.Delegate; if(appdelegate != null) { appdelegate.OrientationLock = orientation; } } public static void LockOrientation(UIInterfaceOrientationMask orientation, UIInterfaceOrientation RotateToOrientation) { LockOrientation(orientation); UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)RotateToOrientation), new NSString("orientation")); } }
视图控制器:
public override void ViewDidAppear(bool animated) { base.ViewWillAppear(animated); OrientationUtility.LockOrientation(UIInterfaceOrientationMask.Portrait, UIInterfaceOrientation.Portrait); } public override void ViewWillDisappear(bool animated) { base.ViewWillDisappear(animated); OrientationUtility.LockOrientation(UIInterfaceOrientationMask.All); }