SwiftUI Sheet关闭按钮无法生效 如何添加顶部X按钮关闭弹窗
实现Sheet顶部X关闭按钮的解决方案
核心修改说明
你遇到的presentationMode不生效的常见原因是未将按钮添加到NavigationView的导航栏区域,或者系统版本适配问题,以下是经过验证的可运行修改方案:
- 优先使用兼容性更强的关闭逻辑,同时支持iOS13及以上所有版本
- 将X按钮添加到导航栏右上角,保证正常显示
- 不依赖环境变量的备用关闭方案也会同时提供
修改后的完整代码
import SwiftUI struct TopicsExperienceCards: View { // 兼容全版本的关闭变量 @Environment(\.presentationMode) var presentationMode // iOS15+ 推荐的新关闭API,可选添加 @Environment(\.dismiss) private var dismiss let etype: EItype // 备用方案:如果环境变量始终失效,可以添加这个绑定属性,从父视图传入sheet的isPresented绑定值 // @Binding var isPresented: Bool var body: some View { NavigationView{ /* Alernatively Page Layout View */ ScrollView (.vertical, showsIndicators: false) { Rectangle() .fill(Color(etype.accentcolor)) .frame(width: 300, height: 5) .padding() GroupBox { TabView { ForEach(etype.content1,id: \.self) {item in VStack (alignment:.center, spacing:0){ Text(item) .padding() .frame(width:300, height:300, alignment:.center) Divider() Spacer() Text("Room for an image") Spacer() Spacer() } } //foreach } //: TABVIEW .tabViewStyle(PageTabViewStyle()) .onAppear { setupAppearance() } } //end of GroupBox .frame(width:350, height:650) .clipShape(RoundedRectangle(cornerRadius: 25.0, style: .circular)) .shadow(radius: 5) } //end of ScrollView .edgesIgnoringSafeArea(.all) // 新增导航栏按钮 .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { // 优先调用适配系统版本的关闭逻辑 if #available(iOS 15, *) { dismiss() } else { presentationMode.wrappedValue.dismiss() } // 备用方案:使用绑定值关闭 // isPresented = false } label: { Image(systemName: "xmark") .foregroundColor(.primary) } } } } //end of Navigation view } } /* Function for the black dots in pagination */ func setupAppearance() { UIPageControl.appearance().currentPageIndicatorTintColor = .black UIPageControl.appearance().pageIndicatorTintColor = UIColor.black.withAlphaComponent(0.2) } struct TopicsExperienceCards_Previews: PreviewProvider { static let etypes: [EItype] = Bundle.main.decode("eibasestructure.json") static var previews: some View { TopicsExperienceCards(etype:etypes[1]) // 备用方案预览时的传值 // TopicsExperienceCards(etype:etypes[1], isPresented: .constant(false)) } }
备用方案使用说明
如果上述环境变量的方式还是无法生效,直接使用绑定值传参的方案100%可用:
- 打开子视图中
@Binding var isPresented: Bool的注释 - 父视图打开Sheet的代码修改为传入绑定值:
@State private var showDetailSheet = false // 调用sheet的位置 .sheet(isPresented: $showDetailSheet) { TopicsExperienceCards(etype: 你要传入的EItype实例, isPresented: $showDetailSheet) }
- 关闭按钮点击逻辑改为
isPresented = false即可
内容的提问来源于stack exchange,提问作者crr-swift
相关产品推荐
相关产品推荐

