深色模式适配一次搞定:Colorful如何用traitCollectionDidChange优雅切换明暗主题
发布时间:2026/8/22 14:40:12 作者:尧图编辑部 阅读量:1,286

深色模式适配一次搞定Colorful如何用traitCollectionDidChange优雅切换明暗主题【免费下载链接】Color-Picker-for-iOSColorful: iOS color picker built with Swift.项目地址: https://gitcode.com/gh_mirrors/co/Color-Picker-for-iOSColorful 是一款用 Swift 编写的 iOS 取色器Color Picker库它在深色模式适配上做了一个非常值得学习的示范借助系统的traitCollectionDidChange回调配合动态颜色一次搞定明暗主题切换无需手动监听通知、也不会出现切一次主题才生效一次的尴尬。为什么深色模式适配总是做不干净很多 iOS 项目遇到深色模式时最常见的翻车姿势有这几种硬编码颜色UIColor(white: 0.89, alpha: 1)写死了浅色值深色下变成一块刺眼的白斑手动监听通知到处监听UIColorAppearance或自定义通知注册时机稍晚就错过首次切换切换后不刷新Layer 上的颜色是快照CGColor不会随主题自动更新切完主题界面还是旧样子。Colorful 的做法是能用系统动态颜色就用必须刷新的 Layer 属性交给每个视图自己的traitCollectionDidChange统一处理。Colorful 的深色模式适配思路动态颜色打底Colorful 的核心 UI 由四个部分组成源码都在Colorful/Classes/目录下组件文件职责色相/饱和度圆盘ColorMapView.swift绘制颜色映射图外圈描边需随主题变化明度滑条BrightnessSlider.swift滚轮式亮度选择边框与阴影渐变随主题变化明度游标BrightnessCursor.swift显示当前色值 HEX圆盘游标ColorMapCursor.swift显示当前选中色在边框这类装饰性颜色上Colorful 优先使用 iOS 13 的动态系统颜色它们会自动跟随外观变化// Colorful/Classes/ColorMapView.swift 中的 updateStrokeColor() let separatorColor: UIColor if #available(iOS 13.0, *) { separatorColor UIColor.tertiarySystemGroupedBackground } else { separatorColor #colorLiteral(red: 0.894, green: 0.894, blue: 0.894, alpha: 1) }明度滑条上下两端的阴影渐变色则使用UIColor.systemBackground打底低版本回退为白色// Colorful/Classes/BrightnessSlider.swift 中的 updateShadowColor() if #available(iOS 13.0, *) { bgColor UIColor.systemBackground } else { bgColor UIColor.white }#available的版本判断让库在 iOS 10 老系统上也能优雅降级——这一点在 Colorful.podspec 中也能印证它的部署目标是 iOS 10.0。✅关键一步用 traitCollectionDidChange 拦截主题切换系统动态颜色能解决 UILabel、UIView 背景色的自动更新但CALayer 上的strokeColor、colors这些 CGColor 是静态快照不会自己变。Colorful 的解法非常克制——在需要刷新的视图里重写一个方法// Colorful/Classes/ColorMapView.swift (L101-L104) override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) updateStrokeColor() }BrightnessSlider里是同样的模式只是多刷新了阴影渐变色// Colorful/Classes/BrightnessSlider.swift (L102-L106) override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) updateBorderColor() updateShadowColor() }这个方法就是 UIKit 在用户切换明暗主题以及尺寸类、对比度等特征变化时自动回调的钩子。用它的好处零手动监听不用注册NSNotification不存在注册晚、泄漏、忘记注销的问题刷新范围最小化谁需要变色谁自己重写ColorMapView只刷描边BrightnessSlider只刷边框和阴影互不干扰时机精准回调时视图已经处于新外观上下文里此时读取UIColor.tertiarySystemGroupedBackground拿到的就是深色值。一个容易被忽略的细节切换瞬间禁用动画注意 Colorful 在更新 Layer 颜色时都包了一层CATransaction.begin() CATransaction.setDisableActions(true) backgounrdLayer.strokeColor separatorColor.cgColor CATransaction.commit()CACurrentTransaction默认会给属性变化加 0.25 秒隐式动画。主题切换的瞬间如果让描边颜色慢慢渐变过去视觉上会显得拖沓。setDisableActions(true)让颜色瞬时完成切换和系统整体外观翻转同步——这个细节让深色模式的切换体验浑然一体。✨快速上手把 Colorful 集成到你的项目Colorful 支持 CocoaPods安装只需两步# Podfile platform :ios, 10.0 pod Colorful, ~ 3.0$ pod install也可以直接克隆仓库查看示例工程Example/目录下有完整的 Demogit clone https://link.gitcode.com/i/4f11983383d604761f793468ae18d915基本用法如下切换颜色时会收到.valueChanged事件let colorPicker ColorPicker(frame: ...) colorPicker.addTarget(self, action: #selector(colorChanged), for: .valueChanged) colorPicker.set(color: .red, colorSpace: .extendedSRGB) view.addSubview(colorPicker)ColorPicker本体定义在Colorful/Classes/ColorPicker.swift它对深色模式是透明的——外观切换完全由内部子视图各自处理调用方什么都不用做。照猫画虎自己项目里适配深色模式的 3 条清单把 Colorful 的做法提炼出来就是三步装饰色优先用系统动态颜色如tertiarySystemGroupedBackground、systemBackground并给老系统留#colorLiteral回退给每个持有 Layer 的视图重写traitCollectionDidChange记得先调super只刷新自己负责的属性用CATransaction.setDisableActions(true)包裹颜色更新让切换瞬时生效。深色模式适配的本质不是多写一遍深色 UI而是让颜色随上下文自动流动。Colorful 用不到 20 行代码就完成了这件事干净、克制值得作为你的参照模板。【免费下载链接】Color-Picker-for-iOSColorful: iOS color picker built with Swift.项目地址: https://gitcode.com/gh_mirrors/co/Color-Picker-for-iOS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考