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

SwiftUI:如何在Bottom Sheet上叠加显示视图?

实现Bottom Sheet上方叠加LoadingView的方案

核心思路

用状态变量控制LoadingView的显隐,通过ZStack把LoadingView叠在Bottom Sheet内容的上层,同时添加半透明遮罩防止用户误触底层内容。

完整代码示例

struct ContentView: View {
    // 控制Bottom Sheet弹出的状态
    @State private var showBottomSheet = false
    // 控制LoadingView显示的状态
    @State private var isLoading = false
    
    var body: some View {
        Button("弹出Bottom Sheet") {
            showBottomSheet = true
        }
        .sheet(isPresented: $showBottomSheet) {
            BottomSheetContent(isLoading: $isLoading)
        }
    }
}

struct BottomSheetContent: View {
    @Binding var isLoading: Bool
    
    // 处理Add按钮点击逻辑
    func handleAddTap() {
        isLoading = true
        // 替换成你的实际业务逻辑,比如网络请求
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            isLoading = false
            // 请求完成后的操作,比如关闭Bottom Sheet
        }
    }
    
    var body: some View {
        ZStack {
            VStack(spacing: 20) {
                // Bottom Sheet的其他内容
                Text("Bottom Sheet内容")
                
                // 你的Add按钮(调整了高度,避免点击区域过小)
                Button(action: handleAddTap) {
                    Text("Add")
                        .padding(.horizontal, 5)
                        .fontWeight(.semibold)
                        .font(.custom("CashMarket-Medium", size: 17))
                        .frame(width: 300, height: 40, alignment: .center)
                }
                .buttonStyle(AddCashbutton())
            }
            
            // 叠加的LoadingView
            if isLoading {
                // 半透明遮罩,阻止底层交互
                Color.black.opacity(0.5)
                    .ignoresSafeArea()
                    .onTapGesture {}
                
                // 加载提示组件
                VStack {
                    ProgressView()
                        .tint(.white)
                        .scaleEffect(1.5)
                    Text("加载中...")
                        .foregroundColor(.white)
                        .padding(.top, 8)
                }
                .padding(20)
                .background(Color.gray.opacity(0.8))
                .cornerRadius(12)
            }
        }
        .padding()
    }
}

// 你的自定义ButtonStyle
struct AddCashbutton: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .background(configuration.isPressed ? Color.blue.opacity(0.8) : Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
    }
}

关键注意点

  • 状态同步:用@Binding传递isLoading状态,确保父视图和Bottom Sheet的状态一致。
  • 按钮高度:原代码里按钮height:10会导致可点击区域极小,建议改成合适高度(比如40),避免点击无响应。
  • 交互阻断:半透明遮罩加上空的onTapGesture,可以防止用户在加载时点击Bottom Sheet的其他内容。

内容的提问来源于stack exchange,提问作者DevExodus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:13:14