SwiftUI中基于Item实现多Sheet层级叠加的解决方案
解决方案:用栈管理Sheet实现叠加效果
核心思路是把原来的单个currentSheet变量改成栈结构,用来记录所有打开的Sheet层级。这样每次打开新Sheet时只是往栈里添加元素,关闭时移除最后一个元素,就能实现Sheet叠加的效果,无需定义多个isPresented或多份Sheet实例。
修改后的完整代码
enum SheetActions: Identifiable { case firstSheet, secondSheet var id: Int { switch self { case .firstSheet: return 1 case .secondSheet: return 2 } } } struct ContentView: View { // 用栈存储Sheet的打开状态,替代单个可选值 @State private var sheetStack: [SheetActions] = [] // 自定义绑定,给sheet(item:)提供当前显示的Sheet(栈顶元素) private var currentSheetBinding: Binding<SheetActions?> { Binding( get: { sheetStack.last }, set: { newValue in if let newValue { // 新Sheet入栈 sheetStack.append(newValue) } else { // 关闭时出栈 if !sheetStack.isEmpty { sheetStack.removeLast() } } } ) } var body: some View { VStack { Button("Open First Sheet") { sheetStack.append(.firstSheet) } .padding() } .sheet(item: currentSheetBinding) { item in switch item { case .firstSheet: FirstSheetView(sheetStack: $sheetStack) case .secondSheet: Text("Second Sheet") .navigationBarTitle("Second Sheet", displayMode: .inline) .navigationBarItems(trailing: Button("Close") { sheetStack.removeLast() }) } } } } struct FirstSheetView: View { @Binding var sheetStack: [SheetActions] var body: some View { NavigationView { VStack { NavigationLink(destination: SecondView(sheetStack: $sheetStack)) { Text("Navigate to Second View") } .padding() } .navigationBarTitle("First Sheet", displayMode: .inline) .navigationBarItems(trailing: Button(action: { sheetStack.removeLast() }) { Text("Close") }) } } } struct SecondView: View { @Binding var sheetStack: [SheetActions] var body: some View { VStack { Button("Open Second Sheet") { // 打开新Sheet时,往栈里添加元素,而非替换 sheetStack.append(.secondSheet) } .padding() } .navigationBarTitle("Second View", displayMode: .inline) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
关键改动说明
- 栈结构替代单个变量:用
[SheetActions]类型的sheetStack存储所有打开的Sheet,栈顶元素就是当前显示的Sheet。 - 自定义Binding:通过
currentSheetBinding把栈的操作和sheet(item:)的要求对接,当Sheet被系统自动dismiss(比如向下滑动)时,也能正确触发栈的出栈操作。 - 打开/关闭逻辑调整:打开新Sheet时调用
sheetStack.append(_:),关闭时调用sheetStack.removeLast(),完美实现层级叠加和逐级关闭。 - 视图传参调整:把原来的
currentSheet绑定换成sheetStack绑定,让子视图也能操作栈结构。
这样修改后,点击「Open Second Sheet」时,新Sheet会直接叠加在当前Sheet之上,关闭时会从最上层开始逐级关闭,完全符合你的需求,且不需要额外定义多个Sheet实例或isPresented变量。
内容的提问来源于stack exchange,提问作者Basel
相关产品推荐
相关产品推荐

