如何禁用SwiftUI中CircularProgressViewStyle样式ProgressView的动画?
解决SwiftUI CircularProgressView动画禁用问题(快照测试专用)
你试过的方法无效,主要是因为CircularProgressView的内置动画(比如无限旋转、进度变化动画)不受普通的animation(nil)或transaction控制,这些动画是组件内部独立驱动的。下面给你几个可靠的方案:
方案1:自定义无动画的圆形进度样式(iOS 15+)
直接实现一个完全静态的ProgressViewStyle,完全绕开系统的动画逻辑:
struct StaticCircularProgressStyle: ProgressViewStyle { func makeBody(configuration: Configuration) -> some View { let progress = configuration.fractionCompleted ?? 0.0 return Circle() .stroke(Color.secondary.opacity(0.3), lineWidth: 4) .overlay( Circle() .trim(from: 0, to: progress) .stroke(Color.accentColor, lineWidth: 4) .rotationEffect(.degrees(-90)) ) .frame(width: 24, height: 24) } } // 使用示例 // 无限加载状态(无进度值) ProgressView() .progressViewStyle(StaticCircularProgressStyle()) // 带进度值的状态 ProgressView(value: 60, total: 100) .progressViewStyle(StaticCircularProgressStyle())
这个样式完全是静态绘制的,没有任何动画,完美适配快照测试。
方案2:用UIKit组件包装(兼容iOS 13+)
如果需要支持更早系统版本,直接用UIKit的组件来替代,手动禁用动画:
针对无限加载的静态指示器:
struct StaticActivityIndicator: UIViewRepresentable { func makeUIView(context: Context) -> UIActivityIndicatorView { let indicator = UIActivityIndicatorView(style: .medium) indicator.stopAnimating() // 直接停止动画,显示静态轮廓 return indicator } func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {} } // 使用 StaticActivityIndicator()
针对带进度值的静态圆形进度:
struct StaticCircularProgress: UIViewRepresentable { let progress: Double func makeUIView(context: Context) -> UIProgressView { let progressView = UIProgressView(progressViewStyle: .circular) progressView.progress = Float(progress) // UIKit的圆形进度默认无动画,直接赋值即可 return progressView } func updateUIView(_ uiView: UIProgressView, context: Context) { uiView.progress = Float(progress) } } // 使用 StaticCircularProgress(progress: 0.5)
方案3:快照测试时的全局动画屏蔽(仅部分场景有效)
如果不想修改视图代码,可以在快照测试代码里给目标视图添加双重动画屏蔽,但注意这个方法对系统CircularProgressView的无限旋转动画可能无效:
let testView = ProgressView() .progressViewStyle(CircularProgressViewStyle()) .environment(\.animation, nil) .transaction { $0.animation = nil } // 执行快照拍摄
为什么你之前的方法没用?
.disabled(true):只禁用交互,不影响动画播放;.animation(nill):拼写错误(应该是nil),而且仅控制视图状态变化时的环境动画,管不了组件内部的循环动画;.transaction { ... }:同样只影响状态变更动画,对系统内置的循环旋转动画无效。
内容的提问来源于stack exchange,提问作者Oliver Pearmain
相关产品推荐
相关产品推荐

