美文网首页
【iOS】ScreenRotator - 屏幕旋转工具类 随时随

【iOS】ScreenRotator - 屏幕旋转工具类 随时随

作者: 健了个平_24 | 来源:发表于2022-10-29 19:57 被阅读0次

    ScreenRotator

    屏幕旋转工具类,能通过代码随时随地改变/保持屏幕方向。

    Feature:
        ✅ 可控制旋转三个方向:
            - 竖屏:手机头在上边
            - 横屏:手机头在左边
            - 横屏:手机头在右边
        ✅ 可控制是否随手机摆动自动改变屏幕方向;
        ✅ 适配iOS16;
        ✅ 兼容 OC & Swift & SwiftUI;
        ✅ API简单易用。
    

    Demo地址

    使用效果

    随时随地改变/保持屏幕方向 `push`或`present`一个跟当前方向不一样的新页面 视频的横竖屏切换

    使用前提

    1. 让单例ScreenRotator.shared全局控制屏幕方向,首先得在AppDelegate中重写:
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return ScreenRotator.shared.orientationMask
    }
    
    1. 不需要再重写ViewControllersupportedInterfaceOrientationsshouldAutorotate

    2. 如需获取屏幕实时尺寸,在对应ViewController中重写:

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        // 🌰🌰🌰:竖屏 --> 横屏
        
        // 当屏幕发生旋转时,系统会自动触发该函数,`size`为【旋转之后】的屏幕尺寸
        print("size \(size)") // --- (926.0, 428.0)
        // 或者通过`UIScreen`也能获取【旋转之后】的屏幕尺寸
        print("mainScreen \(UIScreen.main.bounds.size)") // --- (926.0, 428.0)
    
        // 📢 注意:如果想通过`self.xxx`去获取屏幕相关的信息(如`self.view.frame`),【此时】获取的尺寸还是【旋转之前】的尺寸
        print("----------- 屏幕即将旋转 -----------")
        print("view.size \(view.frame.size)") // - (428.0, 926.0)
        print("window.size \(view.window?.size ?? .zero)") // - (428.0, 926.0)
        print("window.safeAreaInsets \(view.window?.safeAreaInsets ?? .zero)") // - UIEdgeInsets(top: 47.0, left: 0.0, bottom: 34.0, right: 0.0)
        // 📢 想要获取【旋转之后】的屏幕信息,需要到`Runloop`的下一个循环才能获取
        DispatchQueue.main.async {
            print("----------- 屏幕已经旋转 -----------")
            print("view.size \(self.view.frame.size)") // - (926.0, 428.0)
            print("window.size \(self.view.window?.size ?? .zero)") // - (926.0, 428.0)
            print("window.safeAreaInsets \(self.view.window?.safeAreaInsets ?? .zero)") // - UIEdgeInsets(top: 0.0, left: 47.0, bottom: 21.0, right: 47.0)
            print("==================================")
        }
    }
    
    1. 如需监听屏幕的旋转,不用再监听UIDevice.orientationDidChangeNotification通知,而是监听该工具类提供的ScreenRotator.orientationDidChangeNotification通知。或者通过闭包的形式实现监听:
    ScreenRotator.shard.orientationMaskDidChange = { orientationMask in 
        // 更新`FunnyButton`所属`window`的方向
        FunnyButton.orientationMask = orientationMask
    }
    

    API

    全局使用单例ScreenRotator.shared调用:

    1. 旋转至目标方向
    func rotation(to orientation: Orientation)
    
    1. 旋转至竖屏
    func rotationToPortrait()
    
    1. 旋转至横屏(如果锁定了屏幕,则转向手机头在左边)
    func rotationToLandscape()
    
    1. 旋转至横屏(手机头在左边)
    func rotationToLandscapeLeft()
    
    1. 旋转至横屏(手机头在右边)
    func rotationToLandscapeRight()
    
    1. 横竖屏切换
    func toggleOrientation()
    
    1. 是否正在竖屏
    var isPortrait: Bool
    
    1. 当前屏幕方向(ScreenRotator.Orientation)
    var orientation: Orientation
    
    1. 是否锁定屏幕方向(当控制中心禁止了竖屏锁定,为true则不会【随手机摆动自动改变】屏幕方向)
    var isLockOrientationWhenDeviceOrientationDidChange = true 
    // PS:即便锁定了(`true`)也能通过该工具类去旋转屏幕方向
    
    1. 是否锁定横屏方向(当控制中心禁止了竖屏锁定,为true则【仅限横屏的两个方向会随手机摆动自动改变】屏幕方向)
    var isLockLandscapeWhenDeviceOrientationDidChange = false 
    // PS:即便锁定了(`true`)也能通过该工具类去旋转屏幕方向
    
    1. 屏幕方向发生改变的回调
    var orientationMaskDidChange: ((_ orientationMask: UIInterfaceOrientationMask) -> ())?
    
    1. 锁定屏幕方向发生改变的回调
    var lockOrientationWhenDeviceOrientationDidChange: ((_ isLock: Bool) -> ())?
    
    1. 锁定横屏方向发生改变的回调
    var lockLandscapeWhenDeviceOrientationDidChange: ((_ isLock: Bool) -> ())?
    

    可监听的通知

    1. 屏幕方向发生改变的通知:
    • ScreenRotator.orientationDidChangeNotification
      • object: orientationMask(UIInterfaceOrientationMask)
    1. 锁定屏幕方向发生改变的通知:
    • ScreenRotator.lockOrientationWhenDeviceOrientationDidChangeNotification
      • object: isLockOrientationWhenDeviceOrientationDidChange(Bool)
    1. 锁定横屏方向发生改变的通知:
    • ScreenRotator.lockLandscapeWhenDeviceOrientationDidChangeNotification
      • object: isLockLandscapeWhenDeviceOrientationDidChange(Bool)

    兼容 OC & SwiftUI

    • OC:使用专门用OC写的JPScreenRotator,用法和ScreenRotator完全一致。

    • SwiftUI:可以通过ScreenRotatorState来更新状态。

      • 具体使用可以参考Demo中的RotatorView

    Tips

    pushpresent一个跟当前方向不一样的新页面时,建议先旋转,再延时至少0.1s才打开,否则新页面的屏幕方向会错乱。例如:

    let testVC = UIViewController()
    // 1.先旋转
    ScreenRotator.shared.rotation(to: .landscapeRight)
    // 2.延时至少0.1s再打开
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
        if let navCtr = self.navigationController {
            navCtr.pushViewController(testVC, animated: true)
        } else {
            self.present(testVC, animated: true)
        }  
    }
    

    相关文章

      网友评论

          本文标题:【iOS】ScreenRotator - 屏幕旋转工具类 随时随

          本文链接:https://www.haomeiwen.com/subject/shghtdtx.html