Swift中如何优雅的适配黑夜模式(dark mode)

3,540 阅读1分钟

Swift中如何优雅的适配黑夜模式(dark mode)

参考资料:

动态颜色

iOS13 往后,UIColor类增加如下方法:

extension UIColor {    
    @available(iOS 13.0, *)
    public init(dynamicProvider: @escaping (UITraitCollection) -> UIColor)
}

我们可以使用这个方法来创建动态颜色,但是使用的时候总要判断iOS版本号。

为了避免麻烦,我写了个ColorUtil类

class ColorUtil {
  public class func dynamicColor(dark:UIColor, light:UIColor) -> UIColor {
		if #available(iOS 13, *) {  // 版本号大于等于13
      return UIColor { (traitCollection: UITraitCollection) -> UIColor in
        return traitCollection.userInterfaceStyle == UIUserInterfaceStyle.dark ?
                      dark : light
      }
    }
    return light
  }
}

监听模式变化

可以通过如下UIViewController.traitCollectionDidChange来监听:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    if #available(iOS 13, *) {
        if self.traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
            if self.traitCollection.userInterfaceStyle == .dark {
                // 黑夜模式
            } else {
                // 白天模式
            }
        }
    }
}

给导航栏(NavigationBar)设置动态颜色

修改NavigationBar的样式有两种方式:

  • 修改NavigationBar.backgroundColor
  • 通过NaivgationBar.setBackgroundImage(UIImage?, for: UIBarMetrics)设置背景图片

如果使用修改backgroundColor的方法,由于背景图会覆盖在上面,所以需要考虑将背景图片设置成nil即:

self.navigationController?.navigationBar.setBackgroundImage(nil, for: UIBarMetrics.default)
self.navigationController?.navigationBar.backgroundColor = yourDynamicColor

如果使用修改背景图片的方法,则不能使用动态颜色,而应该在traitCollectionDidChange中动态修改背景图片。