如何锁定一个视图控制器的方向仅在斯威夫特肖像模式如何锁定一个视图控制器的方向仅在斯威夫特肖像模式(H

2019-05-10 11:38发布

由于我的应用得到了所有方位的支持。 我想只锁定肖像模式到具体的UIViewController。

(例如,假定它是标签式应用程序,并且登入查看出现模态,我只想要登入查看到肖像模式仅无论用户如何旋转设备或当前设备的方向会如何)

Answer 1:

事情可能会变得相当混乱,当你有一个复杂的视图层次,就像有多个导航控制器和/或标签视图控制器。

此实现将其放在个人视图控制器设置时,他们想锁定的方向,而不是依靠在App代表通过迭代子视图找到他们。

迅速3&4

在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
}

在其他一些全球性结构或辅助类,在这里我创建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")
        UINavigationController.attemptRotationToDeviceOrientation()
    }

}

然后在所需的ViewController您要锁定的方向:

 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(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如果未选中代表将不会被调用。



Answer 2:

斯威夫特4

AppDelegate中

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")
    }
}

您的视图控制器添加以下行,如果你只需要纵向。 你有这适用于所有的ViewController需要显示肖像模式。

override func viewWillAppear(_ animated: Bool) {
AppDelegate.AppUtility.lockOrientation(UIInterfaceOrientationMask.portrait, andRotateTo: UIInterfaceOrientation.portrait)
    }

并且将根据设备的物理取向使屏幕方向为他人的viewController。

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

    }


Answer 3:

添加以下代码以强制纵向和锁定:

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
} 


Answer 4:

这是你的问题和其他相关的一个通用的解决方案。

1.创建附配类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.你的愿望行为创建协议,为您的特定情况下,将画像。

协议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
    }

最后说明:

  • 如果您有更多的类是在纵向模式下,只是延长该协议。
  • 如果从视图控制器希望别人的行为,建立其他协议,并按照相同的结构。
  • 本实施例中解决了与推视图控制器后取向的变化问题


Answer 5:

一群在此线程伟大的答案,但没有很符合我的需求。 我在每个标签导航控制器,以及旋转需要一个视图选项卡式应用程序,而需要其他人被锁定在肖像。 导航控制器不调整它的子视图正确,出于某种原因。 通过与结合中存在(斯威夫特3)解决这个答案,和布局问题消失了。 创建结构由@bmjohns的建议:

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的故事板到新创建的子类。



Answer 6:

要设置横向方向,以您的应用程序的所有视图和只允许一个视图中的所有方向(要能增加相机胶卷为例):

在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
    }
}

然后在Segue公司你希望能够拥有所有方向的一个观点:

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)
    }
}

最后一件事是蜱设备方向: - 纵向 - 横向左 - 右景观



Answer 7:

bmjohns - >你是我生命的救星。 这是唯一的工作液(随着AppUtility结构)

我创建了这个类:

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")
        }

    }
}

并按照您的指示,一切都完全适用于斯威夫特3 - >版本的Xcode 8.2.1



Answer 8:

由于iOS的10和11的,iPad的支持滑过和拆分视图。 为了能够在滑过和拆分视图的应用程序, Requires full screen 必须取消选中。 这意味着,如果应用程序要支持滑过和拆分视图不能用公认的答案。 看到苹果的多任务处理采用更多的增强功能在iPad上 点击这里 。

我有一个允许(1)取消选中一个解决方案Requires full screen ,(2)只有一个函数中实现appDelegate (特别是如果你不想/不能修改目标视图控制器),和(3)避免递归调用。 无需辅助类,也不扩展。

appDelegate.swift(SWIFT 4)

func application(_ application: UIApplication,
                 supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    // Search for the visible view controller
    var vc = window?.rootViewController
    // Dig through tab bar and navigation, regardless their order 
    while (vc is UITabBarController) || (vc is UINavigationController) {
        if let c = vc as? UINavigationController {
            vc = c.topViewController
        } else if let c = vc as? UITabBarController {
            vc = c.selectedViewController
        }
    }
    // Look for model view controller
    while (vc?.presentedViewController) != nil {
        vc = vc!.presentedViewController
    }
    print("vc = " + (vc != nil ? String(describing: type(of: vc!)) : "nil"))
    // Final check if it's our target class.  Also make sure it isn't exiting.
    // Otherwise, system will mistakenly rotate the presentingViewController.
    if (vc is TargetViewController) && !(vc!.isBeingDismissed) {
        return [.portrait]
    }
    return [.all]
}

编辑

@bmjohns指出,此功能不叫iPad上。 我核实,是的,它不叫。 于是,我做了一些更多的测试,发现一些事实:

  1. 我未选中Requires full screen ,因为我想在使滑动并在iPad上幻灯片视图。 这就要求应用程序支持所有4个方向的iPad,在Info.plist中: Supported interface orientations (iPad)

我的应用程序的工作方式相同的Facebook:在iPhone上,大部分时间被锁定为纵向。 当全屏观看图像,让用户更好的视图旋转景观。 在iPad上,用户可以旋转到任何视图控制器的任何方向。 所以,当iPad正在站上的Smart Cover(景观左)的应用程序看起来不错。

  1. 为iPad调用application(_:supportedInterfaceOrientationsFor)在Info.plist中,只保留肖像为iPad。 该应用程序将失去滑过+拆分视图的能力。 但是,你可以锁定或解锁任何视图控制器的方位,在短短的一个地方,无需修改视图控制器类。

  2. 最后,这个函数被调用的视图控制器的生命周期,显示视图时/删除。 如果您的应用程序需要锁定在其他时间/解锁/改变方向,可能无法正常工作



Answer 9:

创建新的扩展

import UIKit

extension UINavigationController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
}

extension UITabBarController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
}


Answer 10:

迅速3&4

设置supportedInterfaceOrientations这样具体UIViewControllers的属性:

class MyViewController: UIViewController {

    var orientations = UIInterfaceOrientationMask.portrait //or what orientation you want
    override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
    get { return self.orientations }
    set { self.orientations = newValue }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    //...
}


Answer 11:

由于上述@ bmjohn的回答。 下面是这个问题的答案的代码的工作Xamarin / C#版本,挽救他人的转录时间:

AppDelegate.cs

 public UIInterfaceOrientationMask OrientationLock = UIInterfaceOrientationMask.All;
 public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
 {
     return this.OrientationLock;
 }

静态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);
    }


Answer 12:

。在我的例子实际测试的解决方案 ,我需要我的整个应用程序应该在人像模式,但只有一个屏幕的方向应该是在横向模式。

代码中的AppDelegate如上答案描述。

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")
}  
}

然后写下此代码之前,您横向视图 - 控制将提交/推。

override func viewWillAppear(_ animated: Bool) {  
super.viewWillAppear(animated)
AppDelegate.AppUtility.lockOrientation(UIInterfaceOrientationMask.portrait, andRotateTo: UIInterfaceOrientation.portrait)
}  

然后写在实际的ViewController该代码(横向视图)

override func viewWillAppear(_ animated: Bool) {  
super.viewWillAppear(animated)
AppDelegate.AppUtility.lockOrientation(UIInterfaceOrientationMask.landscape, andRotateTo: UIInterfaceOrientation.landscape)
}  


Answer 13:

下面是与雨燕4.2(iOS版12.2)对我的作品以简单的方式,把这个在UIViewController您要禁用shouldAutorotate:

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .portrait
}

.portrait部分告诉它在什么方向(S)保持,只要你喜欢,你可以改变这一点。 选项包括: .portrait.all.allButUpsideDown.landscape.landscapeLeft.landscapeRight.portraitUpsideDown



文章来源: How to lock orientation of one view controller to portrait mode only in Swift