💭 让 SwiftUI Sheet 自动调整高度以适应内容

为您每周带来有关 Swift 和 SwiftUI 的精选资讯!

TL;DR: 使用 GeometryReader 测量内容高度并将其传递给 presentationDetents,可让 SwiftUI 的 Sheet 高度根据内容自动调整。结合 .id() 避免高度抖动,使用 ViewThatFits 提高自适应布局效果。

概述

在 SwiftUI 开发中,通过结合 GeometryReaderbackground 的特性,可以让 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. 获取视图高度

使用 backgroundGeometryReader 结合,测量内容视图的实际高度:

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()
}

延伸阅读: