[Android] ベクター形式の画像を取り扱う (Vector Asset Studio)

Classiアドベントカレンダー7日目です。

Androidエンジニアの仕事の大事な点の一つには、
UIデザイナーさんやグラフィックデザイナーさんが考えて作ってくれたデザインや、
アイコンなどを綺麗に表示させることだと考えております。

せっかく細部までこだわって作成してくれたデザインやアイコンの素晴らしさを
余すとこなくユーザーに届けたい・・・

そこで今回は、どの(解像度)端末で(拡大・縮小して)もデザインを損なわず画像を表示させることができる
[VectorDrawable](https://developer.android.com/guide/topics/graphics/vector-drawable-resources.html)の使い方について書きます。

# やりたいこと
ベクター画像(`SVGファイル`、`PSDファイル`、または`マテリアルアイコン`)を取り込んで、Androidアプリケーションに表示させます

- SVGファイル or PSDファイル
<img width="570" alt="スクリーンショット 2017-12-05 1.05.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/152136/0af84453-680e-8aa5-1d3c-68df7c614f6e.png">

- マテリアルアイコン
<img width="261" alt="スクリーンショット 2017-12-05 1.52.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/152136/0445736b-93c8-cb5c-3a45-fb084b6d755c.png">


# どういうもの？

ベクター画像(関連する色情報とともに、点、線、またはカーブの集合をXMLファイルで定義された図形)
を表示する

- 主な利点
    - 同じファイルで、画像の品質を損なうことなく拡大縮小することができます
    - APKファイルが小さくできます
    - 複数のXMLファイルを使用して、アニメーションさせることも可能

# なぜやるか？
- 各解像度ごとに画像を格納するのがめんどくさい
- 少しでもAPKのサイズを小さくしたい
- 少しでもデザイナーさんの役に立ちたい・・・
    - ~~役に立てば、少しは優しくしてくれるかも・・・　~~[^1]

# iOSで対応する場合
- [Assets Catalog](https://developer.apple.com/library/content/documentation/Xcode/Reference/xcode_ref-Asset_Catalog_Format/index.html)を利用します
    - PDF形式のみ

# Androidで対応するには？
- [Vector Asset Studio](https://developer.android.com/studio/write/vector-asset-studio.html#about)を利用する
    - マテリアルアイコン
    - SVG形式または、PSD形式
        - PDF形式は未対応・・・
            - illustratorなどを使用して、SVGまたはPSDに書き出す

# 注意点
- もともと、Android OS 5.0 (APIレベル21)から採用されたもの
    - PNGファイルを生成する方法
    - Support Libraryを使用する方法 ← 今回の対応方法
        - Support Libraryを使用すれば、Android OS 4.4(APIレベル20)以下でも利用できる

# 環境
今回は、以下の環境で試してみました

Android Studio 3.0.1 (1.5以上なら動くようです。)
Gradle 4.1
Android plugin for Gradle 3.0.1


# どうやるの？
### 1. `app/build.gradle` に以下を追加します

```app/build.gradle
defaultConfig {
    vectorDrawables.useSupportLibrary = true
}

・・・

dependencies {
    implementation "com.android.support:appcompat-v7:26.1.0"
}
```

supportライブラリのバージョンは`23.2`以上であれば使えるようです

### 2. Vector Asset Studioを使用します
#### □ 2-1. マテリアルアイコンのベクター画像を作成　します
##### 2-1-1. 「res」フォルダを右クリック => 「New」 => 「Vector Asset」
<img width="697" alt="スクリーンショット 2017-12-05 1.50.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/152136/3b961bcf-71c7-f976-bc68-d0ddbd1031ab.png">
<br>

##### 2-1-2. 「Asset Type：」　Material Icon を選択します
<img width="699" alt="スクリーンショット 2017-12-05 1.50.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/152136/09a2aa39-69f7-f610-c512-8fb7cc336189.png">

※ 「Icon：」 をクリックすると、マテリアルアイコンを選択できます
<img width="723" alt="スクリーンショット 2017-12-05 1.52.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/152136/6781469f-f52f-6c1d-5336-cd3d7968f7ef.png">

##### 2-1-3. 2-1-2で `Name`等を選択後、`Next`ボタンを押下する

##### 2-1-4. Res Directoryを選択して、保存するパスを確認後、`Finish`ボタンを押下する
<img width="709" alt="スクリーンショット 2017-12-05 1.50.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/152136/ac3cf3f8-a292-a7f6-d170-47c3c66cf9bc.png">

##### 2-1-5. `<ResDirectory>/res/drawable/<name>` というxmlが保存されます。

<br>

#### □ 2-2. SVGファイル、PSDファイルを読み込んで、ベクター画像を作成します
##### 2-2-1. 「res」フォルダを右クリック => 「New」 => 「Vector Asset」
##### 2-2-2. 「Asset Type：」　Local file(SVG,PSD) を選択します
- Vector Image Drawableに表示されない場合は、読み込みできていないです。
- エラーが出た場合は、文言に従って解消する

![スクリーンショット 2017-12-05 21.25.28.png](https://qiita-image-store.s3.amazonaws.com/0/152136/e4cfbd08-dfb8-aebe-3956-b3ac9551dfc4.png)

##### 2-2-3. 必要なSizeに変更する

##### 2-2-4. 2-2-3で `Name`等を選択後、`Next`ボタンを押下する
##### 2-2-5. Res Directoryを選択して、保存するパスを確認後、`Finish`ボタンを押下する
##### 2-2-6. `<ResDirectory>/res/drawable/<name>` というxmlが保存されます。
<br>
---
### 3. 今回はImageViewに表示させます
※ DataBindingのため、ルートはlayoutタグになってます
※ ポイントは、`app:srcCompat`です。

```layout/layout.xml
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/logo"
            android:layout_width="128dp"
            android:layout_height="42dp"
            app:srcCompat="@drawable/ic_logo"/>

        <ImageView
            android:id="@+id/icon"
            android:layout_width="50dp"
            android:layout_height="50dp"
            app:srcCompat="@drawable/ic_android_black_24dp"/>
    </LinearLayout>
</layout>
```

### 4. 完成
Android OS 4.4 のエミュレーターでも表示できました :tada: 

<img width="404" alt="スクリーンショット 2017-12-05 21.43.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/152136/40893137-07a3-86aa-8a99-b07226c6b712.png">


### 5. ハマったこと
- SVGファイルで取り込めばOKですが、PSDファイルでは取り込めなかったこと(逆もある)
    - ここは、デザイナーさんの力を借りてしまうこともある。。。

---
# その他、[SVGファイルまたはPSDファイルの考慮事項](https://developer.android.com/studio/write/vector-asset-studio.html#when)
- 単純なアイコンに適しています
- 初期読み込みは、対応するラスター画像と比べて CPU サイクルを余計に消費しがちです
- サイズは最大`200 x 200dp`までに制限することをお勧めします
- 通常は、アイコンの色を`黒（android:fillColor="#FF000000"）`にするのが適切な手法です
    - レイアウトに配置するベクター型ドローアブルがカラーリソースまたはカラーリソースに変換されるテーマ属性を使用でき、合うように自動的に着色されます
- [PSD ファイルのサポートと制限事項](https://developer.android.com/studio/write/vector-asset-studio.html#PSD) があります
- ベクター画像とラスター画像が混在するのでルールを決めましょう

# まとめ
本当は、iOSで使用するPDFをそのまま取り込めれば良いのですが、
なかなかそういうわけにはいきませんでした。。。
しかしながら、ベクター画像を使えば、APKファイルの容量も減るし、
拡大縮小しても綺麗に表示させることができます。
ベクター画像の得意なことを把握して、画像の品質をできる限り落とさずに
拡大縮小をすることができれば、意識しなければいけない部分を減らすことができるかと思います。

Androidは、サポートしなければいけないOSや端末の種類が多いので、
どうしても機種依存による不具合で画像が乱れることもありますが、
いろんな表示方法を知ることで、デザイナーさんの表現をできる限り
そのままユーザに提供できればなと思います。
<Br>


[^1]: Classiのデザイナーさんとモバイルアプリエンジニアはとても仲がいいです