AndroidアプリのアイコンをAdaptive Icon対応にする（Illustrator使用）

Android Oreo（API Level 26）からAdaptive Iconという仕組みが導入され、従来とはアプリアイコンの作り方が大きく変わりました。アイコンの形状をそろえるためのクリッピングは、アプリでは行わず、アプリはその素材を提供するという方式です。

対応するには、background用の素材とforeground用の素材の2つを用意します。単にクリッピングされるだけなので、backgroundもしくはforegroundだけにして片方は空にしてしまっても問題はありません。
分けておけば、それぞれをずらして動かすような効果を作ってくれます。

このbackgroundとforegroundの素材は、それぞれ **108dp x 108dp** の大きさで作成します。
これが任意の形状にクリップされて利用されるわけですが、表示されるエリアは中央の **72dp x 72dp** のエリアで、そこから外側はエフェクト時に使用され、静止状態では表示されないエリアになります。
また、**72dp x 72dp** のエリアをどのようにクリップするかはホームアプリなどが自由に設定しますので、**72dp x 72dp** の矩形そのまま表示されるのか、その内接円が表示されるのか、また別の形状になるのかはわかりません。どのような形状で切り取られてもおかしくないように素材を作る必要があります。

また、中央から**直径66dp**、半径33dpの円の内側はクリップされないセーフゾーン、つまり、このエリアはどのような形状でクリップされても表示されるらしいです。絶対に切り取られては困る部分があるならこのエリアに納めるように配置しましょう。（ただし、このガイドラインがどれだけ守られるのかは不明であり、絶対とは言い切れないとは思います。）

いままでは、アプリアイコンは **48dp x 48dp** でつくるという基準があったにもかかわらず、むしろこのサイズで表示されることの方がまれで、大抵は72dpなどに拡大されて表示されていました。
表示サイズだけみても、やっと本来の使われ方に即したアイコンの作り方ができるようになった感があります。

詳細は公式サイトを参照：
https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive

## Illustratorで旧アイコンをAdaptive Icon対応に

アイコンの作り方はいろいろでしょうけど、私はIllustratorで作っているので、Illustratorで作った旧フォーマットアイコンからAdaptive Iconに対応させてみます。題材は以下のアイコン、単純ですがグラデーションがかかった波線が重なり合い、マイクのシェイプが全面にあるというもの、ドロップシャドウもアイコンの中で書いている状態です。

![](https://qiita-image-store.s3.amazonaws.com/0/155171/7555171e-7060-4168-98f1-c372a697ce2b.png)

さて、これをどのようにforegroundとbackgroundに分解するかですが、ここでは単純に「青背景＋波線」をbackgroundに、「マイクとドロップシャドウ」をforegroundにすることにします。

このアートボードは引き続き単体のアイコン用として必要なのでアートボードを複製して別のアートボードで作業します。

![](https://qiita-image-store.s3.amazonaws.com/0/155171/01207836-35eb-7a8d-e08b-b271d0793ad8.png)

レイヤーも分けておきます。
![](https://qiita-image-store.s3.amazonaws.com/0/155171/6ca87f51-2af0-0d39-7fa6-e75ea389079d.png)

旧アイコンではアートボードのサイズが48 x 48になっているので、これを108 x 108に拡大します。
![](https://qiita-image-store.s3.amazonaws.com/0/155171/80b87270-a716-28d2-812e-25593364c53c.png)
↓
![](https://qiita-image-store.s3.amazonaws.com/0/155171/27c3d03c-9cbf-0a66-4b19-17dce5326804.png)
するとこうなります。
![](https://qiita-image-store.s3.amazonaws.com/0/155171/c4733159-fbb3-f0af-2154-de6a532390d5.png)
foregroundとbackgroundでそれぞれ分離するので、ここでもう一度アートボードを複製してそれぞれをforeground backgroundにします。

![2018-06-24 (11).png](https://qiita-image-store.s3.amazonaws.com/0/155171/ea5fc325-0994-a65c-003d-ac1b8c4d83e0.png)

これを、72dp x 72dpにクリップされる大きさに拡大します。ざっくりとサイズ感をとるには正方形に切り出される場合と、円形に切り出される場合の2パターンを想定すればよいでしょう。もとのアイコンが48dp x 48dpの円形のアイコンだったので、これを単純に72dp x 72dp、つまり1.5倍すれば、円形にクリップされたときにほぼ同じアイコンになります。背景部分を広げておけば正方形に切り出されても問題なさそうなのでその作戦でいきます。

※元のアイコンは円の外側のドロップシャドウを含めるため47dpの円になっていて、中心座標が0.5dp上にズレています。Adaptive Iconではこのようなずらしは不要なのでそれを前提にした調整も必要です。

foregroundにするアートボードから背景部分を削除し、拡大・縮小ツールで拡大します。
![](https://qiita-image-store.s3.amazonaws.com/0/155171/e75a4b31-8dcb-22a8-c09f-311889b036c7.png)

foregroundはこれでOK
![](https://qiita-image-store.s3.amazonaws.com/0/155171/5e4a7a6b-e320-c599-20a6-845051d2d880.png)

次にbackgroundですが、すでに円形にクリップしたシェイプしか残っていないのでもう一度作り直します。

![](https://qiita-image-store.s3.amazonaws.com/0/155171/5ec984d2-16e3-2ee6-95c2-0ed3bf0fdfaa.png)

できたのでそれぞれをSVGで書き出します。
![](https://qiita-image-store.s3.amazonaws.com/0/155171/ee69c15a-86da-4285-9216-601b6f776589.png)

![](https://qiita-image-store.s3.amazonaws.com/0/155171/fa5356f9-a39d-1e92-ca26-31f2c23e857c.png)

## Android Studioへの取り込み

New → Vector AssetでローカルのSVGファイルを指定して取り込みます。
Size:のところにあるOverrideのチェックを入れておきましょう。入れておかないとサイズが24dp x 24dpにされてしまいます。後でXMLを直接編集して直してもいいですが。
![](https://qiita-image-store.s3.amazonaws.com/0/155171/21f59ba5-320c-b725-c6fa-6bee54a1a0eb.png)

backgroundの方は取り込みでエラーが出てしまっていますね。ひとまず取り込んでしまいます。
![](https://qiita-image-store.s3.amazonaws.com/0/155171/107938b2-2b8d-c4ab-da5d-0db0455a4f3b.png)

とりこんだdrawableですが、Adaptive Iconからしか使わないのでdrawable-v26以下に置くようにします。

まずはforeground

```xml:drawable-v26/ic_launcher_foreground.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
  <path
      android:fillColor="#FF000000"
      android:pathData="M54,59.25a4.48,4.48 0,0 0,4.48 -4.5l0,-9a4.5,4.5 0,0 0,-9 0v9A4.49,4.49 0,0 0,54 59.25Z"
      android:strokeAlpha="0.15"
      android:fillAlpha="0.15"/>
  <path
      android:fillColor="#FF000000"
      android:pathData="M62,54.75a8,8 0,0 1,-15.9 0H43.5a10.48,10.48 0,0 0,9 10.08v4.92h3V64.83a10.45,10.45 0,0 0,9 -10.08Z"
      android:strokeAlpha="0.15"
      android:fillAlpha="0.15"/>
  <path
      android:pathData="M54,57.75a4.48,4.48 0,0 0,4.48 -4.5l0,-9a4.5,4.5 0,0 0,-9 0v9A4.49,4.49 0,0 0,54 57.75Z"
      android:fillColor="#fff"/>
  <path
      android:pathData="M62,53.25a8,8 0,0 1,-15.9 0H43.5a10.48,10.48 0,0 0,9 10.08v4.92h3V63.33a10.45,10.45 0,0 0,9 -10.08Z"
      android:fillColor="#fff"/>
</vector>
```
こんな感じになります。いくつか無駄なパラメータがあるので消してしまってもいいでしょう。
（fillAlphaでα値を指定しているのでfillColorの方はARGBではなくてRGBでいいとか、strokeはないのでstrokeAlphaは不要とか）

エラーになったbackgroundの方もみてみましょう。

```xml:drawable-v26/ic_launcher_background.xml
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="24dp"
    android:height="24dp"
    android:viewportHeight="108"
    android:viewportWidth="108">
    <path
        android:fillColor="#2962ff"
        android:pathData="M0,0h108v108h-108z"/>
    <path android:pathData="M100.49,47C88.87,47 88.87,63 77.24,63S65.62,47 54,47 42.37,63 30.74,63 19.12,47 7.49,47A10.55,10.55 0,0 0,0 50V95H108V50A10.56,10.56 0,0 0,100.49 47Z">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endX="54"
                android:endY="47"
                android:startX="54"
                android:startY="95"
                android:type="linear">
                <item
                    android:color="#00FFFFFF"
                    android:offset="0"/>
                <item
                    android:color="#33FFFFFF"
                    android:offset="1"/>
            </gradient>
        </aapt:attr>
    </path>
    <path android:pathData="M90.75,61C79.12,61 79.12,45 67.49,45S55.87,61 44.24,61 32.62,45 21,45C10.17,45 9.42,58.85 0,60.77V93H108V46.83C101.86,51 99.93,61 90.75,61Z"/>
    <path android:pathData="M106.75,59C95.12,59 95.12,43 83.49,43S71.87,59 60.24,59 48.62,43 37,43 25.37,59 13.74,59C6.55,59 3.8,52.87 0,48.2V91H108V58.93C107.6,59 107.18,59 106.75,59Z"/>
</vector>
```
青ベタの矩形と一つ目の波形はうまく変換できているようですが、のこり２つの波形の塗り部分でエラーがでてしまったようです。
しかしpathは健在なので、塗り部分のグラデーション指定だけ手入力で直してあげれば良さそうです。

手入力で修正したのが以下、グラデーションの指定方法については[こちら](https://developer.android.com/reference/android/graphics/drawable/VectorDrawable)を参照

```xml:drawable-v26/ic_launcher_background.xml
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="108dp"
    android:height="108dp"
    android:viewportHeight="108"
    android:viewportWidth="108"
    >
    <path
        android:fillColor="#2962ff"
        android:pathData="M0,0h108v108h-108z"
        />
    <path android:pathData="M100.49,47C88.87,47 88.87,63 77.24,63S65.62,47 54,47 42.37,63 30.74,63 19.12,47 7.49,47A10.55,10.55 0,0 0,0 50V95H108V50A10.56,10.56 0,0 0,100.49 47Z">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endColor="#00ffffff"
                android:endX="54"
                android:endY="95"
                android:startColor="#33ffffff"
                android:startX="54"
                android:startY="47"
                android:type="linear"
                >
            </gradient>
        </aapt:attr>
    </path>
    <path android:pathData="M90.75,61C79.12,61 79.12,45 67.49,45S55.87,61 44.24,61 32.62,45 21,45C10.17,45 9.42,58.85 0,60.77V93H108V46.83C101.86,51 99.93,61 90.75,61Z">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endColor="#00ffffff"
                android:endX="54"
                android:endY="93"
                android:startColor="#33ffffff"
                android:startX="54"
                android:startY="45"
                android:type="linear"
                >
            </gradient>
        </aapt:attr>
    </path>
    <path android:pathData="M106.75,59C95.12,59 95.12,43 83.49,43S71.87,59 60.24,59 48.62,43 37,43 25.37,59 13.74,59C6.55,59 3.8,52.87 0,48.2V91H108V58.93C107.6,59 107.18,59 106.75,59Z">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endColor="#00ffffff"
                android:endX="54"
                android:endY="91"
                android:startColor="#33ffffff"
                android:startX="54"
                android:startY="43"
                android:type="linear"
                >
            </gradient>
        </aapt:attr>
    </path>
</vector>
```

最後に、mipmap-anydpi-v26/ic_launcher.xmlというファイルを作って、そこからこれらを参照すれば完成です。
（一応AndroidManifest.xmlのandroid:icon指定も合っているか確認しましょう）

```xml:mipmap-anydpi-v26/ic_launcher.xml
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
```
AVDのPixel Launcherではこんな感じに表示されました。円形に切り抜いた上でドロップシャドウはホームアプリ側がつけています。
![](https://qiita-image-store.s3.amazonaws.com/0/155171/db3a7994-2b4d-7f5b-9927-9049f114160a.png)

元のアイコンがクリッピングを考慮していないデザインだといろいろと考え直しが必要だとは思いますが、こういうシンプルなアイコンなら比較的簡単に対応できます。