You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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%可用:

  1. 打开子视图中@Binding var isPresented: Bool的注释
  2. 父视图打开Sheet的代码修改为传入绑定值:
@State private var showDetailSheet = false
// 调用sheet的位置
.sheet(isPresented: $showDetailSheet) {
    TopicsExperienceCards(etype: 你要传入的EItype实例, isPresented: $showDetailSheet)
}
  1. 关闭按钮点击逻辑改为isPresented = false即可

内容的提问来源于stack exchange,提问作者crr-swift

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:42:02