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

如何在SwiftUI的Menu中显示ProgressView?

问题:SwiftUI Menu中无法显示ProgressView,如何实现加载中菜单选项?

我想给自己的应用实现一个包含加载中选项的Menu,之前在TV应用里见过这种效果,但不管怎么尝试都没法复现——试过Label、Button、HStack甚至带overlay的Rectangle,ProgressView始终不显示。以下是我尝试的示例代码:

import SwiftUI
struct ContentView: View {
    var body: some View {
        Menu("The menu") {
            ProgressView("some text")

            Button(action: {}) {
                HStack {
                    Text("Button")
                    ProgressView()
                }
            }

            Label {
                Text("Label")
            } icon: {
                ProgressView()
            }

            HStack {
                Text("HStack")
                ProgressView()
            }
        }
    }
}


#Preview {
    ContentView()
}

如截图所示,ProgressView从未出现。请问有没有办法像Apple那样在Menu内显示ProgressView?


解决方案

SwiftUI的Menu组件默认会过滤部分非交互类视图(比如原生ProgressView),导致这些视图无法被正确渲染。要实现加载中菜单选项,可以通过桥接UIKit的UIActivityIndicatorView来绕过这个限制,具体步骤如下:

  1. 创建UIViewRepresentable包装类,桥接UIActivityIndicatorView:
struct ActivityIndicator: UIViewRepresentable {
    var isAnimating: Bool = true
    var style: UIActivityIndicatorView.Style = .medium
    
    func makeUIView(context: Context) -> UIActivityIndicatorView {
        let indicator = UIActivityIndicatorView(style: style)
        indicator.hidesWhenStopped = true
        return indicator
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}
  1. 在Menu中使用这个自定义的ActivityIndicator代替原生ProgressView:
import SwiftUI

struct ActivityIndicator: UIViewRepresentable {
    var isAnimating: Bool = true
    var style: UIActivityIndicatorView.Style = .medium
    
    func makeUIView(context: Context) -> UIActivityIndicatorView {
        let indicator = UIActivityIndicatorView(style: style)
        indicator.hidesWhenStopped = true
        return indicator
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}

struct ContentView: View {
    var body: some View {
        Menu("菜单") {
            // 带右侧加载指示器的按钮
            Button(action: {}) {
                HStack {
                    Text("加载中选项")
                    Spacer()
                    ActivityIndicator()
                }
            }
            
            // 带左侧加载图标的Label按钮
            Label {
                Text("带加载图标的选项")
            } icon: {
                ActivityIndicator(style: .small)
            }
        }
    }
}

#Preview {
    ContentView()
}

原理说明

Menu组件对SwiftUI原生视图的渲染有特定限制,而UIKit的UIActivityIndicatorView属于原生UI组件,Menu会正常渲染这类桥接视图,因此可以实现类似TV应用中的加载中菜单选项效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 22:21:01