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()
}延伸阅读:
"加入我们的 Discord 社区,与超过 2000 名苹果生态的中文开发者一起交流!"