SwiftUI:如何在纵向模式下锁定特定视图,同时允许其他视图更改方向?

Fre*_*Lee 19 orientation swiftui

环境:使用 Swift 5.3 的 SwiftUI
场景:根据Xcode 常规设置,默认方向为Portrait、LandscapeLeft和LandscapeRight。这使得可以按需横向显示,而不是仅将 Xcode 设置为纵向。该项目使用 SwiftUI Lifecycle 与 AppDelegate。

目标:只有特定的视图能够旋转为横向;大多数锁定在肖像。

当前操作方式:设备在当前视图的.upAppear{}中设置为仅纵向模式,并通过onReceive{} 通过设备方向更改通知设置。

我发现这是实际执行瞬时肖像锁定的唯一方法,允许其他人渲染风景。

问题:方向更改通知发生得太晚了:我看到实际的景观正在实时校正 - 因此图像在旋转过程中会弹回。

问题:如何在纵向模式下锁定特定的 swiftUI 视图,以允许其他人自由更改方向?

import SwiftUI
import UIKit

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.blue
            NavigationView {
                Text("Hello, world!")
                    .padding()
                    .navigationTitle("Turkey Gizzards")
                    .navigationBarTitleDisplayMode(.inline)
            }
        }.onAppear {
            UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
        }.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
            UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Law*_*ris 29

没有原生 SwiftUI 方法可以做到这一点。目前看来,必须使用 AppDelegate 适配器。

在您的应用程序主目录中,添加以下内容:

@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
Run Code Online (Sandbox Code Playgroud)

然后添加这个类:

class AppDelegate: NSObject, UIApplicationDelegate {
        
    static var orientationLock = UIInterfaceOrientationMask.all //By default you want all your views to rotate freely

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return AppDelegate.orientationLock
    }
}
Run Code Online (Sandbox Code Playgroud)

并且在设计为锁定为纵向模式的特定视图中:

struct ContentView: View {
    var body: some View {
        ZStack {
            Color.blue
            NavigationView {
                Text("Hello, world!")
                    .padding()
                    .navigationTitle("Turkey Gizzards")
                    .navigationBarTitleDisplayMode(.inline)
            }
        }.onAppear {
            UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation") // Forcing the rotation to portrait
            AppDelegate.orientationLock = .portrait // And making sure it stays that way
        }.onDisappear {
            AppDelegate.orientationLock = .all // Unlocking the rotation when leaving the view
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以根据您的需要,UIDevice.current.setValue(UIInterfaceOrientation.yourOrientation.rawValue, forKey: "orientation")在 onDisappear 中添加另一个,以在离开视图时强制旋转。


sly*_*fox 5

你正在用UIHostingController吗 ?另一种解决方法可能是将其子类化以实现supportedInterfaceOrientations/shouldAutorotate就像我们通常在 UIKit 中所做的那样:

class HostingController<Content>: UIHostingController<Content> where Content: View {}
Run Code Online (Sandbox Code Playgroud)