iOS 横竖屏切换解决方案

1,502 阅读2分钟

之前项目涉及到的都是竖屏的,没有涉及到横屏开发,这次遇到以竖屏为主 部分页面指定横屏,参考了网上的一些方案,终于测试出了一种比较合适的方案,因此将相关内容进行总结一下

01.综述

这次项目主要的页面时竖屏的,会存在连续2或3个页面横屏,在iOS系统16时无论是通过push还是present项目的动画和屏幕的旋转都很完美,但是在低于iOS系统16时push 完全无效果只能采用present模式,同时可以不受手机竖屏锁定

02.项目中设置的配置和代码

截屏2023-08-11 18.11.25.png

此处只选定竖屏一种模式

extension AppDelegate {
   func application(_: UIApplication, supportedInterfaceOrientationsFor _: UIWindow?) -> UIInterfaceOrientationMask {
        return .allButUpsideDown    
  }
}

extension UITabBarController {

    // 是否支持自动转屏

    override var shouldAutorotate: Bool {

        guard let navigationController = selectedViewController as? UINavigationController else { return selectedViewController?.shouldAutorotate ?? false }

        return navigationController.topViewController?.shouldAutorotate ?? false
    }

  


    // 支持哪些屏幕方向

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        guard let navigationController = selectedViewController as? UINavigationController else { return selectedViewController?.supportedInterfaceOrientations ?? .portrait }

        return navigationController.topViewController?.supportedInterfaceOrientations ?? .portrait

    }

  


    // 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)

    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {

        guard let navigationController = selectedViewController as? UINavigationController else { return selectedViewController?.preferredInterfaceOrientationForPresentation ?? .portrait }

        return navigationController.topViewController?.preferredInterfaceOrientationForPresentation ?? .portrait

    }

  


    /// 状态栏样式

    override var preferredStatusBarStyle: UIStatusBarStyle {

        guard let navigationController = selectedViewController as? UINavigationController else { return selectedViewController?.preferredStatusBarStyle ?? .default }

        return navigationController.topViewController?.preferredStatusBarStyle ?? .default

    }

  


    /// 是否隐藏状态栏

    override var prefersStatusBarHidden: Bool {

        guard let navigationController = selectedViewController as? UINavigationController else { return selectedViewController?.prefersStatusBarHidden ?? false }

        return navigationController.topViewController?.prefersStatusBarHidden ?? false
    }

}

extension UINavigationController {

    // 是否支持自动转屏

    override var shouldAutorotate: Bool {

       return  topViewController?.shouldAutorotate ?? false
    }
    // 支持哪些屏幕方向
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
       return topViewController?.supportedInterfaceOrientations ?? .portrait
    }
    // 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return topViewController?.preferredInterfaceOrientationForPresentation ?? .portrait

    }
    /// 状态栏样式
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return topViewController?.preferredStatusBarStyle ?? .default
    }
    /// 是否隐藏状态栏
    override var prefersStatusBarHidden: Bool {
       return topViewController?.prefersStatusBarHidden ?? false
    }

}

基类
extension BaseViewController {
    
    // 是否支持自动转屏
    override var shouldAutorotate: Bool {
      return false
    }
    // 支持哪些屏幕方向
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
      return .portrait
    }
    // 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
      return .portrait
    }
    /// 状态栏样式
    override var preferredStatusBarStyle: UIStatusBarStyle {
      return .default
    }
    /// 是否隐藏状态栏
    override var prefersStatusBarHidden: Bool {
      return false
    }
}
//横屏 子类重写的方法
  extension TestViewController{

       // 支持哪些屏幕方向
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
      return .landscapeRight
    }
    // 默认的屏幕方向(当前ViewController必须是通过模态出来的UIViewController(模态带导航的无效)方式展现出来的,才会调用这个方法)
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
      return .landscapeRight
    }    
}
竖屏跳转横屏

        if  #available(iOS 16.0, *) {
            self.navigationController?.pushViewController(test, animated: true)
            test.setNeedsUpdateOfSupportedInterfaceOrientations()

        }else{
            test.modalPresentationStyle = .fullScreen
            self.present(sport, animated: true)
            UIViewController.attemptRotationToDeviceOrientation()

        }
        
        
一级横屏页面返回 竖屏
       if  #available(iOS 16.0, *) {
            self.navigationController?.popViewController(animated: true)
        }else{
           self.dismiss(animated: true)
        }
        
二级横屏页面返回 竖屏
       if  #available(iOS 16.0, *) {
            self.navigationController?.popViewController(animated: true)
        }else{
            presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
       }