Swift橫豎屏切換、自動旋轉螢幕、手動旋轉螢幕、鎖定當前螢幕禁止轉屏、橫豎屏頁面跳轉過度、橫豎屏UI適配

zk1947發表於2024-07-19

1.AppDelegate中增加螢幕方向屬性UIInterfaceOrientationMask

class AppDelegate: UIResponder, UIApplicationDelegate {
    var orientationLock = UIInterfaceOrientationMask.allButUpsideDown // 預設支援方向   
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return self.orientationLock
    }
}

2.UIWindowScene增加轉屏擴充套件方法

extension UIWindowScene {
    func setInterfaceOrientation(_ orientation: UIInterfaceOrientation) {
        let orientationMask: UIInterfaceOrientationMask
        switch orientation {
        case .portrait:
            orientationMask = .portrait
        case .landscapeLeft:
            orientationMask = .landscapeLeft
        case .landscapeRight:
            orientationMask = .landscapeRight
        default:
            orientationMask = .allButUpsideDown
        }
        
        if #available(iOS 16.0, *) {
            let geometryPreferences = UIWindowScene.GeometryPreferences.iOS(interfaceOrientations: orientationMask)
            self.requestGeometryUpdate(geometryPreferences) { error in
                print("Error requesting geometry update: \(error.localizedDescription)")
            }
        } else {
            UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
            UINavigationController.attemptRotationToDeviceOrientation()
        }
    }
}

3.轉屏

if let windowScene = view.window?.windowScene {
           if windowScene.interfaceOrientation.isPortrait {
                windowScene.setInterfaceOrientation(.landscapeRight)
                // 恢復為支援所有方向
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                    let appDelegate = UIApplication.shared.delegate as! AppDelegate
                    appDelegate.orientationLock = .all
                }
            } else {
                windowScene.setInterfaceOrientation(.portrait)
                // 恢復為支援所有方向
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                    let appDelegate = UIApplication.shared.delegate as! AppDelegate
                    appDelegate.orientationLock = .all
                }
            }
        }

4.監聽螢幕轉動變化重新整理橫豎屏UI

/// 橫豎屏旋轉監聽
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        if traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass {
            // 橫豎屏UI適配
            if UIDevice.current.orientation.isCurrentScreenPortrait() {
                button?.frame = CGRect(x: 10, y: 250, width: UIScreen.main.bounds.width-20, height: 50)
            } else {
                button?.frame = CGRect(x: 80, y: 250, width: UIScreen.main.bounds.width-160, height: 50)
            }
        }
    }

5.鎖定螢幕

if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
            appDelegate.orientationLock = interfaceOrientationMask(from: UIDevice.current.orientation)   
        }
        UIViewController.attemptRotationToDeviceOrientation()

6.解鎖

if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
            appDelegate.orientationLock = .all
        }
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.5, execute: {
            UIViewController.attemptRotationToDeviceOrientation()
        })

demo

相關文章