SwiftUI横竖屏切换时高效追踪视图与屏幕尺寸方案
动态追踪SwiftUI视图与屏幕尺寸的可复用方案(横竖屏适配)
在SwiftUI项目中,我需要动态追踪特定视图尺寸及设备全屏尺寸,核心挑战是保证横竖屏切换时尺寸能正常更新,同时不破坏原有布局。
我基于GeometryReader与PreferenceKey实现了一套可复用方案,能动态捕获子视图和屏幕尺寸,可灵活应用到各类视图中。这里选择用ZStack的原因很明确:GeometryReader默认会占据所有可用空间,很容易打乱原有布局,而ZStack能让尺寸追踪的逻辑仅完成数据捕获,完全不干扰实际内容视图的布局。
具体实现代码
// 定义PreferenceKey用于传递尺寸数据 struct SizePreferenceKey: PreferenceKey { static var defaultValue: CGSize = .zero static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() } } // 视图修饰器:追踪自身尺寸 struct TrackSizeModifier: ViewModifier { func body(content: Content) -> some View { content .background( GeometryReader { geo in Color.clear .preference(key: SizePreferenceKey.self, value: geo.size) } ) } } // 视图修饰器:追踪屏幕全屏尺寸 struct TrackScreenSizeModifier: ViewModifier { func body(content: Content) -> some View { ZStack { content GeometryReader { screenGeo in Color.clear .preference(key: SizePreferenceKey.self, value: screenGeo.size) } .allowsHitTesting(false) // 不拦截交互事件 } } } // 扩展View,提供便捷调用方法 extension View { func trackSize(onChange: @escaping (CGSize) -> Void) -> some View { self .modifier(TrackSizeModifier()) .onPreferenceChange(SizePreferenceKey.self, perform: onChange) } func trackScreenSize(onChange: @escaping (CGSize) -> Void) -> some View { self .modifier(TrackScreenSizeModifier()) .onPreferenceChange(SizePreferenceKey.self, perform: onChange) } } // 使用示例 struct ContentView: View { @State private var viewSize: CGSize = .zero @State private var screenSize: CGSize = .zero var body: some View { VStack(spacing: 20) { Text("当前视图尺寸:\(viewSize.width) x \(viewSize.height)") Text("屏幕尺寸:\(screenSize.width) x \(screenSize.height)") RoundedRectangle(cornerRadius: 10) .fill(Color.blue) .frame(width: 200, height: 200) .trackSize { size in viewSize = size } } .trackScreenSize { size in screenSize = size } .padding() } }
希望各位开发者能针对这套方案提出改进建议,比如优化性能、简化逻辑、适配特殊场景等。
内容的提问来源于stack exchange,提问作者Pramod
相关产品推荐
相关产品推荐

