如何用@State和@Binding实现按钮控制Sheet视图的显示与关闭?
SwiftUI 独立组件实现Sheet打开/关闭示例
核心逻辑是用父视图的@State变量控制Sheet的显示状态,通过@Binding将这个状态传递给所有需要修改它的子组件(打开按钮、关闭按钮),从而实现跨组件的状态同步。
完整代码实现
1. 独立的打开按钮组件(MainButton)
import SwiftUI struct MainButton: View { // 接收父视图传递的Sheet显示状态绑定 @Binding var isSheetPresented: Bool var body: some View { Button("打开Sheet") { // 修改绑定值,触发Sheet展示 isSheetPresented = true } .font(.title) .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(10) } }
2. 独立的关闭按钮组件(NavCloseButton)
struct NavCloseButton: View { // 接收父视图传递的Sheet显示状态绑定 @Binding var isSheetPresented: Bool var body: some View { Button("关闭Sheet") { // 修改绑定值,触发Sheet关闭 isSheetPresented = false } .font(.headline) .padding() .background(Color.red) .foregroundColor(.white) .cornerRadius(8) } }
3. Sheet内容视图(SheetView)
struct SheetView: View { // 接收关闭状态的绑定,传递给内部的NavCloseButton @Binding var isSheetPresented: Bool var body: some View { VStack(spacing: 20) { Text("这是Sheet页面") .font(.largeTitle) // 将绑定传递给关闭按钮 NavCloseButton(isSheetPresented: $isSheetPresented) } .padding() } }
4. 主视图(ContentView)
struct ContentView: View { // 父视图管理Sheet的显示状态 @State private var isSheetPresented = false var body: some View { VStack { Text("主页面") .font(.largeTitle) .padding(.bottom, 50) // 将状态绑定传递给打开按钮 MainButton(isSheetPresented: $isSheetPresented) } .padding() // 通过绑定值控制Sheet的展示/隐藏 .sheet(isPresented: $isSheetPresented) { // 将状态绑定传递给SheetView SheetView(isSheetPresented: $isSheetPresented) } } } // 预览 struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
关键说明
- @State 仅在拥有状态的视图(这里是ContentView)中使用,负责存储Sheet的显示状态。
- @Binding 用于在子组件和父视图之间传递状态引用,子组件可以通过绑定修改父视图的状态,从而触发UI更新(Sheet的打开/关闭)。
- 不管按钮被提取到多少层子组件中,只要通过@Binding传递状态,就能实现状态的同步修改。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

