iOS15真机UIProgressView progressTintColor动画渐变异常如何解决?
问题触发原因
- iOS 15对
UIProgressView的.bar样式底层渲染逻辑做了不兼容更新:该样式默认会关联栏类组件的毛玻璃特效,同时系统会为已填充的进度区域自动添加内置渐变层,你设置的纯白色progressTintColor会被渐变层和毛玻璃效果覆盖,最终呈现灰到白的渐变效果。 - 当前动画实现方式不符合系统规范:
progress属性本身支持自带动画过渡,你直接修改progress为1后调用layoutIfNeeded的写法,在iOS15+会同时触发进度位移、颜色变更的双重隐式动画,进一步放大了系统自带的渐变效果,导致动画初始阶段完全显示为灰色。
适配解决方案
方案1:替换进度条样式(改动最小,适配最快)
直接将.bar样式替换为.default样式,.default样式在全iOS版本都不会自带渐变、毛玻璃特效,原有颜色、圆角配置可以直接生效:
// 仅修改初始化时的样式参数即可 let segment = UIProgressView(progressViewStyle: .default) segment.layer.cornerRadius = 3.0 segment.layer.masksToBounds = true // 其余原有配置保持不变
如果要做版本适配,仅给iOS15及以上版本替换样式:
let segment: UIProgressView if #available(iOS 15, *) { segment = UIProgressView(progressViewStyle: .default) } else { segment = UIProgressView(progressViewStyle: .bar) }
方案2:保留.bar样式,移除系统自带渐变层
如果必须保留.bar样式,可以在初始化时遍历子view移除系统自动添加的渐变层,强制覆盖填充色:
if #available(iOS 15, *) { segment.subviews.forEach { barSubview in // 移除系统自带的渐变层 barSubview.layer.sublayers?.forEach { layer in if layer.isKind(of: CAGradientLayer.self) { layer.removeFromSuperlayer() } } // 强制设置填充色为纯白 barSubview.backgroundColor = Colors.white } }
同时修改动画实现为系统推荐的setProgress写法,避免隐式动画冲突:
// 替换原有动画代码 UIView.animate(withDuration: storyTime, delay: 0, options: .curveLinear) { self.progressBar.setProgress(1.0, animated: true) } completion: { [weak self] _ in guard let self = self else { return } // 原有动画完成逻辑 }
方案3:自定义进度条(彻底解决版本差异)
如果要完全对齐多系统版本的视觉效果,直接用两个UIView实现极简进度条,修改填充视图的宽度约束做动画,完全不受系统API更新影响:
// 自定义进度条示例 let trackView = UIView() trackView.backgroundColor = UIColor.black.withAlphaComponent(0.2) trackView.layer.cornerRadius = 3 trackView.layer.masksToBounds = true let progressView = UIView() progressView.backgroundColor = Colors.white trackView.addSubview(progressView) // 布局时保留进度条宽度约束的引用 var progressWidthConstraint: NSLayoutConstraint! progressWidthConstraint = progressView.widthAnchor.constraint(equalToConstant: 0) // 其余约束:progressView左、上、下等于trackView,高度等于trackView高度 // 动画时直接修改宽度约束 progressWidthConstraint.constant = trackView.bounds.width UIView.animate(withDuration: storyTime, delay: 0, options: .curveLinear) { self.view.layoutIfNeeded() } completion: { _ in // 动画完成逻辑 }
内容的提问来源于stack exchange,提问作者Emre Önder
相关产品推荐
相关产品推荐

