如何在SwiftUI中检测设备旋转并重新绘制视图组件?
当第一个出现时,我有一个@State变量初始化为UIScreen.main.bounds.width的值。但是,当设备方向改变时,该值不会改变。当用户更改设备方向时,我需要重新绘制所有组件。
@dfd提供了两个不错的选择,我添加了第三个选择,这是我使用的一个。
就我而言,我继承了UIHostingController的子类,并在函数viewWillTransition中发布了自定义通知。
然后,在我的环境模型中,我侦听此类通知,然后可以在任何视图中使用。
struct ContentView: View { @EnvironmentObject var model: Model var body: some View { Group { if model.landscape { Text("LANDSCAPE") } else { Text("PORTRAIT") } } } }
在SceneDelegate.swift中:
struct ContentView: View { @EnvironmentObject var model: Model var body: some View { Group { if model.landscape { Text("LANDSCAPE") } else { Text("PORTRAIT") } } } }
我的UIHostingController子类:
window.rootViewCOntroller= MyUIHostingController(rootView: ContentView().environmentObject(Model(isLandscape: windowScene.interfaceOrientation.isLandscape)))
而我的模型:
extension Notification.Name {
static let my_OnViewWillTransition= Notification.Name("MainUIHostingController_viewWillTransition")
}
class MyUIHostingController : UIHostingController where Content : View {
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
NotificationCenter.default.post(name: .my_onViewWillTransition, object: nil, userInfo: ["size": size])
super.viewWillTransition(to: size, with: coordinator)
}
}
@kontiki提供了一种更简单的解决方案,无需通知或与UIKit集成。
在SceneDelegate.swift中:
func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) { model.environment.toggle() }
在Model.swift中:
func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) { model.environment.toggle() }
最终结果是,@EnvironmentObject model
每次环境更改时(无论是旋转还是大小更改),都将重绘依赖的视图。