iOS13 DarkMode适配(一)

avatar
奇舞团移动端团队 @奇舞团

级别: ★☆☆☆☆
标签:「iOS 13」「Dark Mode」
作者: WYW
审校: QiShare团队


前言 笔者最近了解了DarkMode相关的颜色、图片、Web的适配,并且做了一个Demo QiDarkMode,给大家分享一下相关内容。

Dark Mode简介

在iOS 13.0及更高版本中,人们可以选择采用深色系统范围的外观,称为暗模式。Dark Mode(暗模式)是苹果在iOS13推出的新特性。使用iOS13及更高版本的系统的iOS 设备,可以使用暗模式,在暗模式下,系统会采用较暗的视图控件。开发者在开发过程中需要对视图控件进行相应暗模式的适配。

一、DarkMode Demo效果图

笔者分别做了Dark Mode Color、Image、Web的适配示例,分别录制了如下效果图。

QiDarkModeColor.gif

QiDarkModeImage.gif

QiDarkModeWeb.gif

触发Dark Mode 方式

    1. iOS 触发DarkMode的方式除了上图中的方式还可以使用:设置 -> 显示与亮度 -> 切换深色外观 。
    1. 运行项目后,点击Xcode的Environment Overrides ,选择Interface Style的 Light 或 Dark可以切换亮/暗模式。

QiDarkModeWeb.png

    1. macOS触发Dark Mode,需要在在macOS10.14及更高版本的 Mojave系统中才支持,切换暗模式的方式为:系统偏好设置 -> 通用->外观 -> 浅色/深色

二、适配准备

1. @available(iOS 13.0, *)

首先我们在适配Dark Mode的时候,使用相关API需要先写明。

if (@available(iOS 13.0, *)) {
    // Dark Mode适配相关代码
}

上述API写法较长,笔者写了如下一个宏,便于大家使用。使用方式为:QiAvailable(13.0)。

#define QiAvailable(version) @available(iOS version, *)

2. 找到需要背景色文字颜色

苹果官方为开发者提供了一些系统色,我们可以利用结合着文档提示及在Storyboard中测试,选择要填充的背景色。测试选择要使用的文字颜色。

QiDarkModeBackgroundColor.png

QiDarkModeTextColor.png

3. 开发过程中的None、Dark、Light、Any模式

开发过程中会需要设置图片或者颜色的Dark、Light、Any模式下的样式。

Xcode默认的图片和颜色的样式都为None,点击右侧属性中的Appearances可以切换样式为Any,Dark 或 Any,Light,Dark。

相关内容会在下文的中Color Asset部分有所体现。

三、Dark Mode Color

1. 系统色

一般我们可以在基类控制器中写明视图背景色,或基类视图中写明背景色。

如:

self.view.backgroundColor = [UIColor systemBackgroundColor];

textField.textColor = [UIColor placeholderTextColor];

label.backgroundColor = [UIColor tertiarySystemBackgroundColor];

2. 灵活设置颜色

如果我们需要灵活设置视图背景色或文字颜色,可以使用苹果提供的:

+ (UIColor *)colorWithDynamicProvider:(UIColor * (^)(UITraitCollection *traitCollection))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);

如:

if (QiAvailable(13.0)) {
  self.view.backgroundColor = [UIColor systemBackgroundColor];
  
  // 等价于
  // 可以在Dark 和 Light 模式下设置所需的颜色 如Dark下某个接近黑色的颜色 Light下某个接近白色的颜色
  self.view.backgroundColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
      if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleLight) {
          return [UIColor whiteColor];
      } else if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
          return [UIColor blackColor];
      }
      return [UIColor whiteColor];
  }];
}
label.textColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
     if (traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
         return [UIColor lightTextColor];
     } else {
         return [UIColor darkTextColor];
     }
    }];

3. Color Asset

添加Color Asset的方式如下图所示:

QiDarkModeColorAsset.png

可以选择Color Asset 对应的Dark,Light,Any;及Dark,Any 模式下,要显示的颜色。

使用我们创建的Color Asset的方式为:

[UIColor colorNamed:@"StarColor"];

+ (**nullable** UIColor *)colorNamed:(NSString *)name API_AVAILABLE(ios(11.0)); 这个API适用于iOS11及更高版本。

听同事CY说,这个API显示的颜色在iOS11.x的系统上会出现问题,但是苹果在Xcode11正式版已经解决了相关问题。

其中StartColor的配置如下:笔者这里的处理方式为:添加Color Asset,设置Appearance 为Any,Dark。表明笔者只关注Dark模式和非Dark模式,并且设置了非Dark模式显示为蓝色,Dark模式显示为紫色。

QiDarkModeImageColor.png

四、Dark Mode Image

1. 设置Dark、Any模式下的图片

	// Asset中设置多张图片
    UIImage *logoImage = [UIImage imageNamed:@"QiShare"];
    
    UIImageView *logoImageView = [[UIImageView alloc] initWithImage:logoImage];
    logoImageView.frame = CGRectMake(120.0, 100.0, logoImage.size.width, logoImage.size.height);
    [self.view addSubview:logoImageView];

设置多模式下图片的方式如下:选中图片-> 切换Appearance -> 把想要展示的图片拖入到对应模式下。

QiDarkModeImageAsset.png

2. 监听Dark模式改变切换图片

如果我们的图片资源是加载的bundle中的图片。那么可以如下接口中监听模式变化,并且做相应的图片的更新的操作。

- (void)traitCollectionDidChange:(nullable UITraitCollection *)previousTraitCollection API_AVAILABLE(ios(8.0));
@property (nonatomic, strong) UIImageView *logoImageView;
@property (nonatomic, strong) UIImage *lightLogoImage;
@property (nonatomic, strong) UIImage *darkLogoImage;
    self.darkLogoImage = [self qi_imageWithNamed:@"flutterLogo"];
    self.lightLogoImage = [self qi_imageWithNamed:@"QiShare"];
    UIImage *logoImg =self.lightLogoImage;
    
    UIImageView *logoImgV = [[UIImageView alloc] initWithImage:logoImg];
    self.logoImageView = logoImgV;
    [self.view addSubview:logoImgV];
    logoImgV.frame = CGRectMake(100.0, 100.0, logoImg.size.width, logoImg.size.height);

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    [super traitCollectionDidChange:previousTraitCollection];
    
    if (QiAvailable(13.0)) {
        if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
            if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
                self.logoImageView.image =
                self.darkLogoImage;
            } else {
                self.logoImageView.image =
                self.lightLogoImage;
            }
        }
    }
}

3. 改变图片tintColor

不同模式下控制图片显示相应tintColor。

    // tintColor 改变Image着色
    UIImage *starImage = [UIImage imageNamed:@"star"];
    starImage = [starImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    UIImageView *starImageView = [[UIImageView alloc] initWithImage:starImage];
    starImageView.frame = CGRectMake(100.0, 220.0, starImage.size.width, starImage.size.height);
     starImageView.tintColor = [UIColor colorNamed:@"StarColor"];
    [self.view addSubview:starImageView];

注意+ (**nullable** UIColor *)colorNamed:(NSString *)name API_AVAILABLE(ios(11.0)); 这个API 是从iOS11.0开始支持的。

设置tintColor生效的一个注意点:

// UIImageRenderingModeAlwaysTemplate:Always draw the image as a template image, ignoring its color information
// 忽略图片的颜色信息 把图片作为模板图片来绘制
// 图片的显示颜色由tintColor控制

五、Dark Mode Web

在macOS10.14 Mojave系统中支持Dark Mode,切换暗模式和亮模式的方式为:系统偏好设置 -> 通用->外观 -> 浅色/深色。

下边的内容是笔者参考Dark Mode Support in WebKit:写的一个简单H5文件,大家有需要的话,可以提供给前端同学查看。相关内容,笔者也已经在Demo中使用本地加载的方式测试过,可以在不同模式下,正常切换。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Qi测试DarkMode</title>
	
<style>

:root {
    color-scheme: light dark;
    --special-text-color: black;
	
    --bg-color: white;
}

@media (prefers-color-scheme: dark) {
    :root {
		--special-text-color: white; 
        --bg-color: black;
    }
}

.special {
    color: var(--special-text-color);
    background-color: var(--bg-color);
}
	
body
{
	background-color:var(--bg-color);
}
h1
{
	color:var(--special-text-color);
	text-align:center;
}
p
{
	color:var(--special-text-color);
	font-family:"Times New Roman";
	font-size:20px;
}
	

	</style>
</head>

<body>

<h1>测试DarkMode标题</h1>
<p>DarkMode段落。</p>

	<picture>
	<source srcset="http://img.zcool.cn/community/012b62554b2b0e000001bf72f9aad7.jpg@2o.jpg" media="(prefers-color-scheme: dark)">
	<img src="http://p0.so.qhmsg.com/t0184f2659879a11464.jpg", width="300">
</picture>

</body>
</html>

六、Demo

详情见Demo:QiDarkMode

参考学习网址


了解更多iOS及相关新技术,请关注我们的公众号:

小编微信:可加并拉入《QiShare技术交流群》。

关注我们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)

推荐文章:
2019苹果秋季新品发布会速览
申请苹果开发者账号的流程
Swift 5.1 (3) - 字符串
用Flutter 写一个简单页面
5分钟,带你迅速上手Markdown语法
Swift 5.1 (2) - 运算符
Swift 5.1(1) - 基础
Sign In With Apple(一)
奇舞周刊