Androidの色リソースを整理した話 〜 Material Designの色パレットの名前を使おう

Androidアプリをやっていると、だんだんとapp/res/values/colors.xmlが肥大化していきます。
早いうちに、色の命名規則であったり、リソースを追加するときの基準を考えておいたほうが良いです。

# 課題：使いたいけど使えない色が増えてしまった……

少人数チームで開発をしていると、エンジニアが自分で画面をデザインしなければならない場面に遭遇します。
おそらく、チームにデザイナーがいたとしても、カラーコードまでは設定してくれても、Androidの色リソースの名前まで指定してくれるデザイナーは少ないかと。

## 現状

開発をしながら、指定された色を、colors.xmlに追加していくと、こんなことに……。

* 「お知らせ画面で使う色だから、`official_information_gray`ね」（#F5F5F5）
* 「明るい系のグレーがにしたいから、`light_gray`を追加ー」（#F6F6F6）
* 「メニューのグレーが必要なんですか、はい`menu_gray`ねー」（#707070）
* 「グレーが必要なのね、はい`gray`ねー」（#757575）
* 「Material Designにしていこう、gray_600って名前、明るさがわかって便利ー」（#757575）
* など………

上のようにリソースを追加していくと……
`official_information_gray`と`light_gray`は、RGB値それぞれ1しか差がなく、目で見りゃどっちも同じ。`menu_gray`と`gray`も5しか差がないし、`gray`と`gray_600`に至っては全く同じ！

```xml:色リソースの例
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="item_border_gray">#aaaaaa</color>
    <color name="light_gray">#f6f6f6</color>
    <color name="official_information_gray">#f5f5f5</color>
    <color name="red">#f44336</color>
    <color name="pressed_red">#c01e07</color>
    <color name="blue">#0000ff</color>
    <color name="background_gray">#f0f0f0</color>
    <color name="selected_list_item">#f8f8f8</color>
    <color name="dark_gray">#a9a9a9</color>
    <color name="gray_500">#9E9E9E</color>
    <color name="menu_gray">#707070</color>
    <color name="gray">#757575</color>
    <color name="gray_600">#757575</color>
    <color name="gray_800">#424242</color>
    <color name="red_50">#ffebee</color>
    <color name="red_100">#ffcdd2</color>
    <color name="status_purple">#c084dc</color>
    <color name="transparent_black">#55000000</color>
    <color name="facebook_blue">#3a589b</color>
    <color name="twitter_blue">#598dca</color>
    <color name="transparent">#00000000</color>
</resources>
```

## 問題点

### ドキュメント内のリソース名を変更するのが大変になる

例えば、redのリソースをred_500とかに置換する時……。
ドキュメント全体に対して「red」で検索をかけると、「**Shared**Preference」「**Preferred**Size」などの英単語も引っかかって置換が面倒くさい（正規表現使えばいいのだけれど）

### grayだけ言われても、どれくらいの明るさなのかわからない

gray, light_grey, dark_grey、確かにこの3つがあればわかる気もしますが、そもそもgrayの明るさが、ど真ん中（#808080）とは限りません。lightもどれくらいの差を持って明るいのか、darkもしかり、差がわかりませんね。

### 使う場所はわかるけど、どんな色なのかわからない

結局、名前的に使いづらいリソースになってしまうんです……。

# 改善案：colors.xmlはすべてMaterial Designのパレットを基準にする

colors.xmlには、基本的には以下のような基準で追加してくのはどうでしょうか。

基本的には、Material Designのカラーパレットに準拠させる。
https://www.google.com/design/spec/style/color.html

カラーパレットにない色に関しては、以下の検討をする。

* 色が指定されている（ロゴで決められている、画像リソースに合わせる）場合
    * 用途をはっきりさせた名前で、colorを追加する
* どうしても使用する場所や用途の名前で使いたい、多くの箇所で使用している
    * stylesに定義することを検討する

こうすることによって、**エンジニアがコーディング・デザインどちらも気持ちよく開発できる**ようになります。

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--Material Color-->
    <color name="red_50">#ffebee</color>
    <color name="red_100">#ffcdd2</color>
    <color name="red_500">#f44336</color>
    <color name="red_900">#B71C1C</color>
    <color name="blue_900">#0D47A1</color>
    <color name="gray_50">#FAFAFA</color>
    <color name="gray_100">#F5F5F5</color>
    <color name="gray_400">#BDBDBD</color>
    <color name="gray_500">#9E9E9E</color>
    <color name="gray_600">#757575</color>
    <color name="gray_800">#424242</color>

    <!--プロフィール画面ステータス-->
    <color name="status_purple">#c084dc</color>
    <!--プレミアムコラム一覧 最新投稿のテキスト背景-->
    <color name="transparent_black">#55000000</color>
    <!--Facebookボタン-->
    <color name="facebook_blue">#3a589b</color>
    <!--Twitterボタン-->
    <color name="twitter_blue">#598dca</color>
    <!--ListViewのSelector用-->
    <color name="transparent">#00000000</color>
</resources>
```

すっきりしましたね！！

# 更に！拡張してみる試み（パレットにない色も、命名してみたい）

Material Designのパレットだと、色彩用語でいうと、**色相**と**明度**しか表現できていません。HSV（HSB）の色空間に触れたことのある方であれば、**彩度**の情報が足りないことがわかると思います。

これらの用語について、念のため説明を入れておくと……
**色相（Hue）**とは、色み。赤いのか、青いのか、黄色いのか、といったもの。HSV（HSB）の色空間では、[色相環](https://ja.wikipedia.org/wiki/%E8%89%B2%E7%9B%B8#.E8.89.B2.E7.9B.B8.E7.92.B0)に従い、色相を360度の角度で表現します。
**明度（Value・Brightness）**は、読んで字のごとく、色の明るさです。最も最低の値は、**黒**。明度が最大の値を取ると……白？と思いますが、HSV（HSB）の色空間だとちょっと違います。HSV（HSB）における明度は、次に解説する「彩度」と共に、2次元の空間を作っています。そのため、明度が最大でも、彩度の値が0でない限り、真っ白にはなりません。詳しくはコチラ→[HSV色空間](https://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93#HSV.E3.81.A8.E8.89.B2.E8.A6.9A)
**彩度（Saturation）**は、色の鮮やかさを示します。最低値では、グレーの階調の色に（いわゆる白黒）。最高値は、ビビッドな、原色と言われるような色になります。

## 命名の方針（案）

### (案1)後ろに数字を追加する（色相\_明度\_彩度）
Material Designの命名は、直感的に分かりやすいと思っています。これに倣って、`red_500_50`（red_500を基準に、彩度を50%にした色）のように、彩度に関する情報を後ろに追加するとかはいかがでしょうか。

### (案2)HSVの色空間の名前で表現する（色名\_彩度\_明度）
案1では、確かに直感的だったのですが、そもそも、`red_500_50`が実際どんな色かイメージできるでしょうか。案外難しいと思います。じゃぁ、そのままHSBで書いてしまいましょう、という方法です。例えば、`red_50_100`と書くと、彩度を50、明度を100にした色合いだということがわかります。

### (案3)いっそPCCSの命名を使う？
案2ではHSV（HSB）の色空間を応用した命名をしましたが、もう少し直感的な気がするのは**表色系**と用いた命名をすること。**色空間**が「絶対的に**色を指定すること**」を目的とするなら、**表色系**は「間違いなく**色を伝えること**」を目的とした体系です。

ここでは、「PCCS（Practical Color Co-Ordinate System）」と呼ばれる表色系を命名の参考にすることを提案します。PCCSでは、「色相、彩度、明度」を数値やアルファベットを使って表現します。こうすることで、色をイメージしやすくしています。詳しくは、サイトを御覧ください。（参考：http://www.nanisama.com/color/system/pccs/）

でもやっぱり分かりづらいなぁ。

## 結論「パレットをつくりましょう…」

これまで案を出してきましたが、「これなら結局RGBの値をそのまま名前にしたほうがイメージしやすいよ！(´；ω；｀)」という人も出てきそうです。それはどうしてかと言えば、エンジニアにとって、RGBの色空間は、**エンジニア共通の色見本 = パレット**として機能しているからだと思います。

Material Designの命名を使うと色リソースを使いやすくなった背景には、数字の付け方の規則がシンプルだっただけでなく、サイトに行けば色が選べて、あらゆる色が既に命名されている状態になっていた（= パレットが出来上がっていた）ことも要因としてあると思います。つまり、それが、**チーム共通の色見本=パレット**になったから、色を使いやすくなったのだと思います。

Material Design以外の名前にしたい場合は、可能な限り多くの色バリエーションで、既に名前をつけたパレットを作ることが有効かもしれません。それができないのであれば、定期的に、すべての色リソースを棚卸しして、整理することをおすすめします。

色リソースを整理しただけのお話でしたが、なにか参考になればと思います。