iOS Chameleon 教程:开始

原文:Chameleon on iOS: Getting Started
作者:Keegan Rush
译者:kmyhy

颜色构成了美!我们的身边充斥着颜色,app 中也无例外。但添加到 app 中的颜色很难管理,这些颜色有的互相关联,有的则不。最糟糕时,如果颜色组合使用不当,会导致 app 可视化元素会难于辨识。所以 Chameleon (变色龙)就出现了!

它是一种颜色管理框架,允许你轻松地将一系列颜色添加到你的 app 中。在本文中,你将学习如何使用 Chameloen:

  • 利用 Chameleon 调色板区分 UI 元素
  • 创建随机色
  • 用十六进制创建 UIColor
  • 根据你的喜好对整个 app 进行样式调整
  • 动态生成颜色方案
  • 通过对比色保持 label 的显示
  • 通过和背景色的对比保持状态栏图标始终可见

本文假设你熟悉 iOS 开发和 Swift。如果你不熟悉,请看一下我们的 iOSSwift 教程。

开始

开始项目叫做 HomeSplash,是一个用于室内设计的 app。你可以用它来对某些东西着色,比如家具,将它们加上不同的颜色,看看它们在卧室中的效果(后续集成 ARKit)。你可以在本文顶部或底部找到开始项目的下载按钮。

下完后,打开 HomeSplash.xcworkspace,Build & run。你会看到一个颜色拾取器,选择某个颜色,看看它添加到家具上是个什么样子。

看一下这个项目,你会发现它有两个 view controller:

  • ViewController.swift: 根 view controller ,包含了用于展示家具的 image view。
  • ColorPickerViewController.swift: 调色板,选择颜色后会刷新根 view controller。

还有一个使用 Core Image 对图片进行着色的工具类 ImagePainter.swift。选择暂时不用管这个类。

我知道你在想些啥。作为一个和颜色有关的 app,它目前还是太单一了。不用担心,你将对它进行升级。

你将实现这些内容:

  • 将 UIKit 颜色改成 Chameleon 的调色板
  • 基于颜色方案将不同颜色应用到不同对象
  • 通过一个 +/- 控件来控制家具的加亮和加暗效果
  • 如果你对它的艺术感不太满意,还可以生成一些随机色
  • 通过全局主题,将整个 app 的主题换成指定的颜色

创建拾色器

看一眼 Chameleon 的 API,你就发现它大量使用了 flat 颜色。为什么?

什么叫做 flat 颜色?

Flat 颜色通常也叫做固定色,通常颜色的渐变和色调不会变化或者变化很小。它们也没有透明度,alpha 值为 1.0。在 Chameleon 中,当提到 flat 颜色时,它指的就是 Chameleon 的 flat 调色板中的颜色。

Flat 调色板是一个 24 种常用色的集合,它们分成两种颜色浓度,加起来组成了 48 种色。当使用 Chameleon 生成一种 flat 颜色时,它会从中选取一种。

将 flat 颜色添加到拾色器

打开 Main.storyboard 找到 Color Picker Scene.

每个颜色方块表示用户可以使用的一个颜色。现在,它们使用的是原生的 UIKit 颜色。所有颜色通过故事板来设置,因此如果你想在这里使用 flat 颜色,必须安装 Chameleon 故事板插件。

下载 Chameleon 调色板,你可以在 Chameleon 的 GitHub 主页上找到它。它使你能够在 IB 中使用 Chameleon 颜色。

下完后,打开,运行 Palette Installer.pkg.

安装时会有一个安全警告。阅读完警告之后,请在 Mac 安全和隐私设置中同意安装。

要继续安装,你需要点击“总是打开”。

安装完成后,重启 Xcode 并打开 Main.storyboard.

在 Color Picker Scene 中选择一个 Color Views,打开属性面板。

点击 Background 属性右边的下拉框,选择 Other…。拾色器会显示。

点击第三个 tab (调色板按钮),你会看到 Color View 的所用的颜色会显示在苹果的调色板中。这是默认调试版,你可以使用标准颜色比如 UIColor.green。

打开调色板中的下拉列表,你会看到有许多调色板可以选择,包括我们刚刚添加的 Chameleon 调色板。选择它,你会看到有许多漂亮的颜色可以使用。

选择其中一种,应用到故事板的 9 个 Color View 中。Build & run,你会看到这些颜色。

在代码中使用 Chameleon 的 flat 颜色非常简单 —— 和 UIKit 颜色差不多。它们是在 UIColor 扩展中进行声明的,只不过加以 flat 前缀:

let flatMint = UIColor.flatMint
let flatMintDark = UIColor.flatMintDark

随机颜色

生成随机色的一般办法是将一个随机值传递给 UIColor.init(red:green:blue:)。用这种方法,经常会出现颜色组不太协调的结果。

在 Chameleon,有一种更完美和简单的解决办法,它减少了随机性。例如:

// 从 flat 调色板中选择一个随机色
let randomFlatColor = UIColor.randomFlat

// 从 flat 调色板的 24 种浅色中选择一个随机色
let randomLightFlatColor = UIColor(randomFlatColorOf: .light)

// 从数组中选择一个随机色
let myFavoriteColors = [UIColor.red, UIColor.flatGreen, UIColor(white: 0.5, alpha: 1.0)]
let randomColorFromArray = UIColor(randomColorIn: myFavoriteColors)

// 从 flat 调色板中选择一个随机色但排除数组中的颜色
let reds = [UIColor.flatRed, UIColor.flatRedDark]
let random = UIColor(randomFlatColorExcludingColorsIn: reds)

你会发现大部分方法和属性是从 flat 调色板中返回一个颜色。但 UIColor(randomColorIn:) 例外,它返回的是指定数组中的颜色。

添加随机颜色到拾色器

当前,在拾色器中的“Random”按钮什么也不做。是时候用 Chameleon 来做点什么了。

打开 ColorPickerViewController.swift ,导入 Chameleon :

import ChameleonFramework

找到 andomColorTapped(_:)方法,添加:

let randomColor = UIColor.randomFlat
updateAndPop(color: randomColor)

这会从 Chameleon 的调色板中生成一个随机颜色。然后将颜色传递给第一个 view controller.

Build & run。点击一个家具,跳到拾色器。然后,点击 Random 按钮。呀,你未来的卧室会用随机色进行配色。

16 进制颜色码

你可能会发现,Ray Wenderlich Green 按钮也不工作。你接下来就解决这个——因为说真的,谁不喜欢将自己的家具配成 Ray 最爱的绿色呢?

Ray Wenderlich 绿的 16 进制颜色值是 #0B560E。但在标准的 UIColor 构造方法中,却没有 16 进制到 RGB 颜色值的转换器。

在 ColorPickerViewController 中找到 rayWenderlichGreenTapped(_:)方法,添加:

let rayWenderlichGreen = UIColor(hexString: "0B560E")!
updateAndPop(color: rayWenderlichGreen)

这会用 16 进制值创建一个 UIColor,然后取代所选的颜色。

Build & run,看看将卧室配成 Ray Wenderlich 绿后的样子,惊不惊喜吧?

颜色方案

当你使用多种颜色时,你需要确保它们能够彼此协调。事实上,错误的颜色组合可以让 UI 显得不协调或者刺眼。幸好,和我一样没有艺术细胞的人可以使用颜色方案。

所谓配色方案,是指拥有一定关联的颜色集。Chameleon 能够生成 3 种颜色方案:

  • Analogous 相近色
  • Complementary 互补色
  • Triadic 三元色

相似色是那些在色盘上彼此相邻的颜色。

它们在色谱上彼此相邻。它们也会彼此混合。

互补色在色盘上彼此对立。

它们的这种对立让 UI 变得显眼和生动。

三元色在色盘上均等分布。

这种配色能够用在色彩鲜艳的设计上。

通过选定颜色来创建配色方案

打开 Main.storyboard 找到第一个 view controller. 上面有一个 segmented 控件,默认的标题是 First, Second, Third :

点击 segmented control ,打开属性面板。
将每个 title 分别修改为:

  • Segment 0: Analogous
  • Segment 1: Complementary
  • Segment 2: Triadic

光光修改 title 并不会改变其功能。要修改功能,需要打开 ViewController.swift ,导入 Chameleon.

import ChameleonFramework

然后,在 selectedColor 增加一个属性:

var selectedColorScheme = ColorScheme.analogous {
  didSet {
    paintImages()
  }
}

它定义了一个配色方案,初始值为 ColorScheme.analogous。当修改它时会调用 paintImages()。

现在,找到 colorSchemeSelectionChanged(_:)方法, 新加下列代码,修改 selectedScheme 的值:

switch sender.selectedSegmentIndex {
case 0:
  selectedColorScheme = .analogous
case 1:
  selectedColorScheme = .complementary
case 2:
  selectedColorScheme = .triadic
default:
  return
}

这个 switch 语句根据所选择的 segment 来改变 selectedColorScheme 的值。

好了!选定的配色方案已经被改变了,我们需要用它来绘制图片。

paintImages() 会为每个 image view 创建 UIImage,然后用指定颜色来渲染它们。是时候修改这个方法,让它用颜色方案中的颜色来绘制图片了。将 paintImages() 方法修改为:

func paintImages() {
  let baseColor = selectedColor

  // 1
  let colorsFromScheme = ColorSchemeOf(selectedColorScheme,
                                       color: baseColor,
                                       isFlatScheme: false)

  // 2
  imageView.image = imagePainter.paint(image: UIImage(named: "sofa"),
                                       color: colorsFromScheme[1])
  imageView2.image = imagePainter.paint(image: UIImage(named: "armchair"),
                                        color: colorsFromScheme[2])
  imageView3.image = imagePainter.paint(image: UIImage(named: "bookshelf"),
                                        color: colorsFromScheme[3])
}

详细解释一下这段代码:

  1. 用所选择的配色方案生成一组颜色。
  2. 针对每张图片,从 colorsFromScheme 数组中挑选一个颜色用于绘制图片。第 2 个索引位置的颜色是 selectedColor。你会用它来给中间的图片上色。

Build & run。选中一种颜色,看一下你的新设计如何!

颜色深浅

通过配色方案的使用,卧室的颜色数量增长了 3 倍。现在,你可以通过改变颜色深浅来增加更多颜色!

在 Main.storyboard 中,看一下 Stepper 控件。

它的初始值是 0,而取值范围是 -100 到 100。它的增减幅度是 10。你可以用它的值乘以某个百分比来改变选中颜色的浓或者淡。

在 ViewController.swift 中找到 selectedColor, 在它下面添加:

var selectedColorWithShade: UIColor {

// 1
  let shadePercentage = CGFloat(abs(stepperValue / 100))

  if stepperValue >= 0 {
// 2
    return selectedColor.lighten(byPercentage: shadePercentage)!
  } else {
// 3
    return selectedColor.darken(byPercentage: shadePercentage)!
  }
}

解释如下:

  1. stepperValue 用于保存 stepper 的值。将这个数变成一个 0 到 1.0 之间的浮点数,用来表示颜色深浅的百分度。
  2. 如果 stepper 的值是正数,调用 lighten(byPercentage:) 让颜色加亮。
  3. 如果 stepper 值是负数,调用 darken(byPercentage:) 让颜色加暗。

回到 paintImages(),那是见证奇迹的地方。方法的第一行代码设置了用于创建配色方案的颜色。

let baseColor = selectedColor

将它改成:

let baseColor = selectedColorWithShade

好了!Build & run,点击 stepper。

设置 app 主题

拾色器的最后一种形式完成!但 app 自身仍然看起来比较呆板。幸好,Chameleon 仍然还有办法。

在 ViewController.swift 的 updateAppTheme() 中,当你修改 selectedColor 时会触发这个方法。将这个方法修改为:

Chameleon.setGlobalThemeUsingPrimaryColor(selectedColor, with: .contrast)

在你庆祝之前,你已经修改了整个 app 的主题!

Build & run,选择一个新颜色,看看新代码为 app 带来什么改变。

但是还有几个问题。例如,拾色器中的标准 UIButton 使用新主题后不太好看。

幸好,可以用样式化来解决。在 ColorPickerViewController.swift 中,找到 styleButtons() 方法。添加下列代码,让按钮看起来更舒服一点:

buttons.forEach {
  $0.layer.cornerRadius = 10
  $0.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
}

button 是一个 IBOutletCollection 集合,包含了 Random 和 Ray Wenderlich Green 按钮。styleButtons() 方法将每个按钮进行圆角化,然后通过一个 inset 增加了内白。Build & run 查看变化。

在使用全局 app 主题时,还有一个地方值得注意。你是不是对 updateAppTheme 中添加的代码中的 .contrast 感到好奇嘛?它是一个 UIContentSytle。

它的可能取值是:

UIContentStyle.contrast
UIContentStyle.light
UIContentStyle.dark

Build & run,从拾色器中选择一个深色,看一下拾色器中按钮的文字颜色:

现在,选择一种浅色。

UIContentStyle.contrast 确保文本总是可见的,在深色背景中它是白字,在浅色背景中它就是黑字。

通过全局 app 主题,能让你的 app 大部分时候都变得漂亮,但仍然有一些问题要解决!比如,导航条仍然是白色的。如果它能匹配 app 的主题就更好了。这需要你在 ViewController.swift 的 updateAppTheme() 方法中修改它的 tintColor :

navigationController?.navigationBar.barTintColor = selectedColor

Build & run。选择几个颜色。

哇哦!导航条颜色仍然不对。title 不会根据 tint color 而变。状态栏也不会变,很不容易看出它来。

谢天谢地,Chameleon 仍然能够搞定!

加入对照色

要解决返回按钮和导航栏标题颜色的问题,需要让导航栏标题色和 selectedColor 成为对照色。在 updateAppTheme() 最后面添加:

let contrastingColor = UIColor(contrastingBlackOrWhiteColorOn:selectedColor, 
                               isFlat: true)
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor : contrastingColor]

好!添加之后的 updateAppTheme() 方法应该是这个样子。

func updateAppTheme() {
  Chameleon.setGlobalThemeUsingPrimaryColor(selectedColor, with: .contrast)
  navigationController?.navigationBar.barTintColor = selectedColor
  let contrastingColor = UIColor(contrastingBlackOrWhiteColorOn:selectedColor, isFlat: true)
  navigationController?.navigationBar.titleTextAttributes = 
    [.foregroundColor : contrastingColor]
}

接下来再次 build & run。这次,导航栏的文字颜色和背景色就是对照色了。

前面用 setGlobalThemeUsingPrimaryColor(_:with:) 设置全局 app 主题时,也会影响到状态栏。但为什么没有变呢?

要搞定状态栏的问题,需要打开 Info.plist。找到 Information Property List,点击 + 按钮增加一个新属性。name 输入 View controller-based status bar appearance ,类型选择 Boolean ,value 设为 NO.

这使得 Chameleon 能够控制状态栏。Build & run,你会发现状态栏的返回按钮、标题、状态栏全都会随你所选择的颜色而变。

渐变色

你已经使用了全局 app 主题,也为使这些颜色互相兼容做了一些工作。但是,仍然还需要做一件事情,让你的 app 更显眼。

在 ViewController.swift 的 showColorPicker(_:)方法,在调用 navigationController?.pushViewController 之前加入:

colorPicker.view.backgroundColor = selectedColor

这会将拾色器的背景色设置为你选中的颜色。Build & run 看下。

噢,不!选择的颜色遮住了按钮、导航栏和其它颜色。这里使用一个渐变色会更合适。你可以让拾色器中的空白部分显示一些颜色,而其余部分保持白色背景就好。

将你在 showColorPicker(_:) 添加的那句代码修改为:

colorPicker.view.backgroundColor = UIColor(gradientStyle: .topToBottom,
                                           withFrame: colorPicker.view.frame,
                                           andColors: [.flatWhite, .flatWhite, 
                                                       selectedColor])

这会将背景色设置为从上到下的渐变色。2/3 的上部是 Chameleon 的 flat 白,而底部的 1/3 是你所选的颜色。colorPicker.view.frame 让 Chameleon 知道如何用不同颜色来填充渐变。

搞定了!Build & run,看一下最终成果。

接下来是什么?

就像你看到的,Chameleon 允许你在 app 中更轻松地使用颜色和主题。你可以用顶部或底部的 Download Materials 按钮下载项目的的最终版本。

别忘了看 Chameleon 的文档,以了解最新特性。

想了解更多色觉理论吗?编译我们的 iOS 教程的这个项目将帮助你理解 UI 设计。

和本教程、Chameleon 和色觉理论有关的问题,请留言在下边!

Download Materials

猜你喜欢

转载自blog.csdn.net/kmyhy/article/details/80856928