iOS切换明暗模式后GradientView渐变颜色不更新的修复咨询
问题:切换深色/浅色模式后GradientView渐变颜色不更新
当App处于深色/浅色模式时,将App退到后台,在手机设置中切换模式后返回App,自定义的GradientView不会重新绘制渐变颜色。虽然traitCollectionDidChange触发了updateColors方法,但渐变颜色没有发生变化。使用的自定义动态颜色本身适配正常,问题仅出在GradientView上。
原代码实现
GradientView代码
final class GradientView: UIView { var locations: [NSNumber]? = [0.0, 1.0] { didSet { updateLocations() } } var colors: [CGColor]? = [Color.backgroundPrimary.withAlphaComponent(0).cgColor, Color.backgroundPrimary.cgColor] { didSet { updateColors() } } var gradientLayer: CAGradientLayer { layer as! CAGradientLayer } override public class var layerClass: AnyClass { CAGradientLayer.self } convenience init(_ from: CGColor, _ to: CGColor) { self.init(frame: .zero) colors = [from, to] } override func layoutSubviews() { super.layoutSubviews() updateLocations() updateColors() } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { if #available(iOS 13.0, *) { if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) { self.updateColors() } } } } private extension GradientView { func updateLocations() { gradientLayer.locations = self.locations } func updateColors() { gradientLayer.colors = self.colors } }
自定义动态颜色代码
public static var backgroundPrimary = dynamicColor(light: colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1), dark: colorLiteral(red: 0.0, green: 0.0, blue: 0.0, alpha: 1))
问题原因
核心问题在于colors属性存储的是静态的CGColor值:
- 初始化时,
Color.backgroundPrimary.cgColor会根据当前模式生成对应的CGColor并存储。 - 当系统模式切换后,动态UIColor
Color.backgroundPrimary会更新,但之前存储的CGColor不会自动同步变化。 - 调用
updateColors时,只是把旧的CGColor重新赋值给渐变层,所以颜色不会更新。
修复方案
修复后的代码
final class GradientView: UIView { var locations: [NSNumber]? = [0.0, 1.0] { didSet { updateLocations() } } // 将属性类型改为UIColor,保留动态颜色的适配能力 var colors: [UIColor]? = [Color.backgroundPrimary.withAlphaComponent(0), Color.backgroundPrimary] { didSet { updateColors() } } var gradientLayer: CAGradientLayer { layer as! CAGradientLayer } override public class var layerClass: AnyClass { CAGradientLayer.self } // 调整初始化器参数为UIColor convenience init(_ from: UIColor, _ to: UIColor) { self.init(frame: .zero) colors = [from, to] } override func layoutSubviews() { super.layoutSubviews() updateLocations() updateColors() } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { if #available(iOS 13.0, *) { if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) { updateColors() } } } } private extension GradientView { func updateLocations() { gradientLayer.locations = self.locations } func updateColors() { // 每次更新时,根据当前traitCollection获取对应模式的CGColor gradientLayer.colors = colors?.map { color in if #available(iOS 13.0, *) { return color.resolvedColor(with: traitCollection).cgColor } else { return color.cgColor } } } }
关键修复点
- 存储UIColor而非CGColor:保留动态颜色的特性,确保模式切换时能获取到对应颜色值。
- 动态获取当前模式的CGColor:在
updateColors中,通过resolvedColor(with: traitCollection)方法获取当前模式下的UIColor,再转换为CGColor赋值给渐变层,保证每次更新都是最新的颜色。 - 适配初始化逻辑:调整便利初始化器的参数类型为UIColor,保持接口一致性。
内容的提问来源于stack exchange,提问作者kesape
相关产品推荐
相关产品推荐

