TL;DR: 使用
GeometryReader
测量内容高度并将其传递给presentationDetents
,可让 SwiftUI 的 Sheet 高度根据内容自动调整。结合.id()
避免高度抖动,使用ViewThatFits
提高自适应布局效果。
概述
在 SwiftUI 开发中,通过结合 GeometryReader
和 background
的特性,可以让 Sheet 高度根据内容动态调整,并将其传递给 presentationDetents
。以下是详细步骤和关键实现。
示例代码
完整示例代码可在 此处获取。
使用示例
Swift
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("显示 Sheet") {
showSheet.toggle()
}
.adaptiveSheet(isPresented: $showSheet) {
Text("动态高度内容")
.frame(maxWidth: .infinity, minHeight: 300)
}
}
}
实现步骤
1. 获取视图高度
使用 background
和 GeometryReader
结合,测量内容视图的实际高度:
Swift
.background(
GeometryReader { proxy in
Color.clear
.task {
// 获取子视图高度
subHeight = proxy.size.height
}
}
)
Color.clear
确保布局不受干扰。.task
实时绑定高度到变量。
2. 动态调整 Sheet 高度
将子视图高度绑定到 presentationDetents
:
Swift
.sheet(isPresented: $isPresented) {
sheetContent
.presentationDetents([.height(subHeight)])
}
.height(subHeight)
确保高度随内容动态调整。
注意事项
1. 初次弹出防抖动
利用隐藏的 background
提前测量内容尺寸,避免 Sheet 初次弹出时高度抖动。
2. 动态高度刷新问题
结合 .id()
确保视图在高度变化时正确刷新:
Swift
.sheet(isPresented: $isPresented) {
sheetContent
.id(subHeight)
.presentationDetents([.height(subHeight)])
}
3. 自适应布局支持
通过 ViewThatFits
,优化内容在不同屏幕尺寸下的适配:
Swift
ViewThatFits {
CompactContentView()
FullContentView()
}