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

SwiftUI中如何在显示加载指示器时禁用视图交互?

解决SwiftUI加载指示器显示时无法禁用用户交互的问题

你当前给Loading视图添加allowsHitTesting(false)的做法是错误的——这个修饰符会让加载视图不接收任何点击事件,点击会直接穿透到下层的按钮,所以按钮依然能被触发。正确的思路是让加载视图接收点击事件,从而拦截下层所有交互元素的点击。

具体修改步骤

  1. 给Loading视图添加绑定变量,用来控制加载状态的显示/隐藏(实际应用中可根据API请求状态切换该值);
  2. 移除Loading及其子视图上的allowsHitTesting(false),让加载视图默认接收点击,实现拦截下层交互的效果;
  3. 在ContentView中添加状态变量,控制加载视图的显示逻辑。

修改后的完整代码

Loading视图代码

import SwiftUI

struct Loading: View {
    @Binding var isShowing: Bool
    
    var body: some View {
        if isShowing {
            ZStack {
                BlurView()
                    .allowsHitTesting(true)
                VStack {
                    Indicator()
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .edgesIgnoringSafeArea(.all)
        }
    }
}

struct BlurView: UIViewRepresentable {
    func makeUIView(context: UIViewRepresentableContext<BlurView>) -> UIVisualEffectView {
        let effect = UIBlurEffect(style: .systemMaterial)
        let view = UIVisualEffectView(effect: effect)
        return view
    }
    
    func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<BlurView>) {}
}

struct Indicator: UIViewRepresentable {
    func makeUIView(context: UIViewRepresentableContext<Indicator>)-> UIActivityIndicatorView {
        let ind = UIActivityIndicatorView(style: .medium)
        ind.startAnimating()
        return ind
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {}
}

ContentView代码

import SwiftUI

struct ContentView: View {
    @State private var isLoading = true // 实际开发中根据API请求状态切换该值
    
    var body: some View {
        NavigationView {
            ZStack {
                VStack {
                    Button {
                        print("Button tapped")
                    } label: {
                        Text("Tap me")
                    }
                    .frame(width: 200, height: 60)
                    .background(.red)
                    
                    Spacer()
                }
                
                Loading(isShowing: $isLoading)
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

效果说明

当isLoading为true时,加载视图会铺满整个屏幕并接收所有点击事件,下层按钮无法被触发;加载完成后将isLoading设为false,加载视图消失,按钮恢复可交互状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 03:30:46