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

macOS SwiftUI中ProgressView无法修改色调颜色的问题求助

macOS SwiftUI ProgressView 无法修改颜色的解决办法

在开发macOS SwiftUI应用的搜索功能时,需要在搜索执行时显示ProgressView,但尝试了.tint()、.foregroundStyle()、CircularProgressViewStyle(tint:)等方法都无法修改指示器颜色,始终显示默认的白/灰色。唯一可行的方式是设置.preferredColorScheme(.light),但这会改变整个应用的主题,体验很差。环境为macOS Ventura 13.5,构建目标macOS 12.4。

方案1:自定义圆形进度指示器样式

SwiftUI在macOS上的默认ProgressView样式对tint的支持有限,可以自行实现自定义ProgressViewStyle,完全控制颜色与动画:

struct CustomCircularProgressViewStyle: ProgressViewStyle {
    var tint: Color = .black
    
    func makeBody(configuration: Configuration) -> some View {
        Circle()
            .trim(from: 0, to: CGFloat(configuration.fractionCompleted ?? 0))
            .stroke(tint, style: StrokeStyle(lineWidth: 2, lineCap: .round))
            .rotationEffect(.degrees(-90))
            .frame(width: 16, height: 16)
            .animation(.linear(duration: 1).repeatForever(autoreverses: false), value: configuration.fractionCompleted)
    }
}

// 使用示例
ProgressView(value: 0.5)
    .progressViewStyle(CustomCircularProgressViewStyle(tint: .black))

如果仅需要无限旋转的加载动画,无需精确进度值,可简化为:

struct InfiniteCircularProgressView: View {
    var tint: Color = .black
    
    var body: some View {
        Circle()
            .trim(from: 0.2, to: 1)
            .stroke(tint, style: StrokeStyle(lineWidth: 2, lineCap: .round))
            .rotationEffect(.degrees(0))
            .animation(.linear(duration: 1).repeatForever(autoreverses: false), value: UUID())
            .frame(width: 16, height: 16)
    }
}

方案2:用NSViewRepresentable包装NSProgressIndicator

直接使用AppKit的NSProgressIndicator组件,可完全控制其外观属性:

struct AppKitProgressView: NSViewRepresentable {
    var tint: Color = .black
    var isAnimating: Bool = true
    
    func makeNSView(context: Context) -> NSProgressIndicator {
        let indicator = NSProgressIndicator()
        indicator.style = .spinning
        indicator.controlSize = .small
        indicator.isDisplayedWhenStopped = false
        indicator.color = NSColor(tint)
        return indicator
    }
    
    func updateNSView(_ nsView: NSProgressIndicator, context: Context) {
        if isAnimating {
            nsView.startAnimation(nil)
        } else {
            nsView.stopAnimation(nil)
        }
    }
}

// 使用示例
AppKitProgressView(tint: .black)

修改你的SearchBar代码

将原代码中的ProgressView替换为自定义组件即可,比如使用AppKitProgressView:

// 替换原SearchBar中ProgressView的部分
if isSearching {
    AppKitProgressView(tint: .black)
        .scaleEffect(0.75)
}

额外说明

macOS上的SwiftUI ProgressView底层依赖NSProgressIndicator,系统默认样式会受系统外观(深色/浅色模式)的强约束,导致tint设置失效。自定义样式或直接使用AppKit组件可绕过这一限制,实现完全的颜色控制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:52:38