LoginSignup
178
153

More than 5 years have passed since last update.

VectorDrawable対応まとめ

Last updated at Posted at 2016-03-13

2016/04/12(火)追記

23.3.0から、 app:srcCompatsetImageResouce()でしかVectorDrawableが適用されなくなったようです。詳しくはSupport Vector Drawableのバージョン間差異についてに詳しく書かれています。


DroidKaigi公式アプリのアイコンをVectorDrawableにして各解像度ごとのpngファイルをほとんど消すことができたので、対応した内容をまとめておこうと思います。
Suppoort vector drawable #345

下準備

1. Gradleの設定

gradleのbuild toolバージョンをv2.0に上げます。

build.gradle
buildscript {
    ...
    dependencies {
        ...
        classpath 'com.android.tools.build:gradle:2.0.0-beta6'
        ...
    }
}

build.gradleのdefaultConfigに以下を追加します。

build.gradle
android {
  ...
  defaultConfig {
    ...
    vectorDrawables.useSupportLibrary = true
    ...
  }
}

もしbuild tool v1.5.0以下を使い続けなければならない場合は、以下のように記述します。

android {
  defaultConfig {
    // Stops the Gradle plugin’s automatic rasterization of vectors
    generatedDensities = []
  }
  // Flag to tell aapt to keep the attribute ids around
  aaptOptions {
    additionalParameters "--no-version-vectors"
  }
}

2. Support Libraryのアップデート

appCompatのバージョンを23.2.0に上げます。
support-vector-drawableは明示的に追加しなくても大丈夫です。

build.gradle
dependencies {
    ...
    compile "com.android.support:appcompat-v7:23.2.0"
    compile "com.android.support:support-vector-drawable:23.2.0"
    compile "com.android.support:animated-vector-drawable:23.2.0"
    ...
}

詳しくは、以下の記事が詳しいので参考にしてください。
AppCompat v23.2 — Age of the vectors

VectorDrawableの作成

Vector Asset Studioなどを使って既存のアイコンと同じVectorDrawableを作っていきます。詳しくは以下を参照してください。

既存のアイコンからVectorDrawableを作る

対応箇所

ImageViewのanodroid:srcやTextViewのanodroid:drawableLeft、Notificationのiconなど、それぞれどう対応していったのかをまとめます。

1. ImageViewのandroid:src

xmlの中のandroid:srcapp:srcCompatに変えるだけです。

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_search"/>

コードで指定する場合は、setImageResourceを使えばOKです。

imageView.setImageResource(R.drawable.ic_search);

2. TextViewのandroid:drawableLeft

TextViewの場合は、直接VectorDrawableを指定すると落ちます。
そのため、StateListDrawableを作成してその中でVectorDrawableを指定してあげる必要があります。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_access_time_grey_500_12dp_vector" />
</selector>
<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:drawableLeft="@drawable/ic_access_time_grey_500_12dp_vector_state"
    android:drawablePadding="@dimen/icon_spacing_small"
    android:drawableStart="@drawable/ic_access_time_grey_500_12dp_vector_state"

3. ContextCompat.getDrawable()

何もしなくてOKです。AppCompat23.2.0からは内部のアイコンもVectorDrawableを使っていますし、基本的に~Compatクラスを使っていれば何も対応はいらないはずです。

4. android.support.design.widget.NavigationView

menuの中のandroid:iconにVectorDrawableを指定すればそのまま動きます。

drawer_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_all_sessions"
            android:icon="@drawable/ic_event_note_grey_600_24dp_vector"
            android:title="@string/all_sessions" />
        ...
    </group>

</menu>

5. Toolbarのメニューアイコン

AppCompatActivityを使っていれば、VectorDrawableを指定するだけでOKです。

menu_sessions.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/item_search"
        android:icon="@drawable/ic_search_white_24dp_vector"
        android:orderInCategory="100"
        android:title="@string/search"
        app:showAsAction="always" />

</menu>

6. Notificationのアイコン

Lollipop未満はまだ未対応です。
Lollipop以上はdrawable-v21ディレクトリに入れたVectorDrawableを指定するだけでOKです。

Notification notification = new NotificationCompat.Builder(context)
    .setContentIntent(pendingIntent)
    .setSmallIcon(R.drawable.ic_stat_notification_vector)
    ...

7. GoogleMapのマーカー

BitmapDescriptorFactory.fromResource()を使うと落ちます。
一度Bitmapに変換して、fromBitmap()を使って対応しました。
VectorDrawableをBitmapに変換する

8. Drawableを指定するUIライブラリ

内部でBitmapDrawableにキャストしていたりすると落ちます。
もし対応していない場合は、ライブラリにPullRequestを送って対応しましょう。
DroidKaigiアプリの場合、LikeButtonが対応していなかったのでPullRequestを送りました。
https://github.com/jd-alexander/LikeButton/pull/17

VectorDrawableの属性の説明

主要な属性をまとめておきます。詳しくは公式のVectorDrawableのリファレンスを見てください。

タグ 属性 説明
vector android:width 表示する横幅。dpで指定します。
vector android:height 表示する縦幅。dpで指定します。
vector android:viewportWidth 書き出したVectorの横幅px。px(数値)で指定します。
vector android:viewportHeight 書き出したVectorの縦幅px。px(数値)で指定します。
vector android:autoMirrored RTLで反転させるアイコンの場合、trueを指定します。
path android:fillColor pathの色。透過は指定しても無視されます。
path android:fillAlpha pathの透過度。0.0(透明)〜1.0を指定します。
path android:pathData 画像のpath。

対応時に気になりそうなところ

以下対応時の雑感です。

どのくらいapkサイズが減るの?

DroidKaigiアプリの場合、29個のアイコンをVectorDrawableに変えたことで、200KBほど減りました。
Suppoort vector drawable #345

AppCompat v23.2 — Age of the vectorsによると、AppCompat自体も70KB減らせたらしいです。

Allows AppCompat to use vector drawables itself. This itself has shaved off around 70KB from AppCompat’s AAR (~9%).

対応はめんどくさいところもありますが、アイコンの数だけ効果は出るという感じですね。

どういう仕組みなの?

実際にVectorDrawableをどう解釈しているのかはわかりませんが、VectorDrawableCompatが適用されるまでの流れは以下に詳しくまとまっています。
Support LibraryのVectorDrawableCompatが適応されるまでの仕組み

これからはVectorDrawableにすべきなの?

Vectorにすべきなんじゃないでしょうか。
最近のGoogleのOSS plaidも、全てVectorDrawableで作られていますね。

色の変更も楽ですし、採用しない理由は特になさそうです。AndroidStudioのプレビューがまだうまく表示できてない部分がありますが、そのうち対応してくれるはずです。

命名や置き場所はどうするべき?

plaidを真似て、drawableの中に入れることにしました。

ファイル名は、アイコンの場合は ic_xxxx_vector.xmlのようにsuffixに_vectorをつけることにしました。vector以外のアイコンも混在しているため、ぱっと見てVectorDrawableだとわかるようにしたかったからです。

TextViewのdrawableLeftなどで使うのにStateListDrawableを作る必要がある場合は、ic_xxxx_vector_state.xmlのようにしました。ここはどうするべきかまだ決めかねています。

起動時のオーバーヘッドは?

内部を見てないので体感でしかないですが、特に感じませんでした。

ビルド時間に影響はないの?

内部を見てないので体感でしかないですが、特に感じませんでした。

参考資料

1. AppCompat v23.2 — Age of the vectors

基本的なVectorDrawable導入方法がまとまっています。

2. Support LibraryのVectorDrawableCompatが適応されるまでの仕組み

内部でどのようにVectorDrawableCompatが適用されていくかが詳しく説明されています。

3. VectorDrawableリファレンス

VectorDrawableの属性やメソッドが全てまとまっています。

4. Vector Asset Studio

svgファイルからVectorDrawableを作成するAndroidStudioのツールの説明です。

5. plaid

Googleの中の人が作っているOSSです。アイコンは全てVectorDrawableで作られています。

178
153
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
178
153