我正在尝试使用以下代码从纵向视图呈现横向视图
Button {
isLandscapeViewPresented.toggle()
} label: {
Text("Click for landscape view")
}.fullScreenCover(isPresented: $isLandscapeViewPresented) {
LandscapeOnlyView {
LandscapeView()
}
}
在 LandscapeOnlyView 包装器中我有如下
struct LandscapeOnlyView<Content: View>: UIViewControllerRepresentable {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { }
func makeUIViewController(context: Context) -> some UIViewController {
return LandscapeHostingController(rootView: content)
}
}
对于持有 rootview 的 LandscapeHostingController 如下:
class LandscapeHostingController<Content: View>: UIHostingController<Content> {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscape
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
AppDelegate.orientationLock = .landscape
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
scene?.requestGeometryUpdate(.iOS(interfaceOrientations: .landscapeRight), errorHandler: { error in
print(error)
})
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
AppDelegate.orientationLock = .portrait
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
scene?.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait), errorHandler: { error in
print(error)
})
}
}
我正在使用 AppDelegate,正如您所看到的,我在哪里更新了orientationLock,只要我需要更改方向,supportedInterfaceOrientations 覆盖就会返回更新后的方向。
我得到以下输出。
我需要 LandscapeView 甚至在呈现之前就处于横向状态,这与上面显示的情况不同,其中视图切换到横向,因为方向更新是在 LandscapeHostingController 包装器的 viewWillAppear 中完成的,以实现快速 ui 视图。
我尝试过很多方法。我的方法有什么问题应该改变吗?
关于如何实现它有什么想法吗?
要将 SwiftUI 应用程序中视图的方向锁定为仅横向,您需要在
UIViewController
中或通过基于场景的更新来管理方向。下面是一种简化的方法,可确保视图在出现之前锁定在横向中。
代码示例:
import SwiftUI
struct LandscapeOnlyView<Content: View>: UIViewControllerRepresentable {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
func makeUIViewController(context: Context) -> UIViewController {
let controller = UIHostingController(rootView: content)
controller.modalPresentationStyle = .fullScreen
return LandscapeViewController(rootViewController: controller)
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}
class LandscapeViewController: UIViewController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscape
}
override func viewDidLoad() {
super.viewDidLoad()
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
scene?.requestGeometryUpdate(.iOS(interfaceOrientations: .landscapeRight), errorHandler: nil)
}
}
struct ContentView: View {
@State private var isLandscapeViewPresented = false
var body: some View {
Button("Open Landscape View") {
isLandscapeViewPresented.toggle()
}
.fullScreenCover(isPresented: $isLandscapeViewPresented) {
LandscapeOnlyView {
Text("This view is locked in landscape orientation")
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
.foregroundColor(.white)
}
}
}
}
这可确保
LandscapeView
在出现之前锁定横向方向,解决您所描述的问题。