Android

VectorDrawableをBitmapに変換する

More than 3 years have passed since last update.

Support Library v23.2.0でVectorDrawableCompatが追加されたことにより、Lollipop未満のバージョンでもVectorアイコンが使えるようになりました。

使い方は簡単。ImageViewは android:srcの代わりに app:srcCompat を使うだけです。TextViewの android:drawableLeft などの場合も、StateListDrawableを作って中にVectorDrawableを指定すれば動きます。

詳しくは以下を参照。


VectorDrawableが直接使えないケース

ただ、GoogleMapのマーカーアイコンなどはまだVectorDrawableを直接指定することはできません。下記のようにvectorアイコンを指定すると落ちます。StateListDrawableを使っても同じです。

new MarkerOptions()

.position(new LatLng(latitude, longitude))
.title("タイトル")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_place_vector)); // コレ


ic_place_vector.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#F44336"
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z" />
</vector>



Bitmapに変換する

VectorDrawableをBitmapに変換することで対応しました。

new MarkerOptions()

.position(new LatLng(latitude, longitude))
.title("タイトル")
.icon(BitmapDescriptorFactory.fromBitmap(ResourceUtil.getBitmap(context, R.drawable.ic_place_vector))); // コレ


ResourceUtil.java

public class ResourceUtil {

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static Bitmap getBitmap(VectorDrawable vectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
return bitmap;
}

private static Bitmap getBitmap(VectorDrawableCompat vectorDrawable) {
Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
return bitmap;
}

public static Bitmap getBitmap(Context context, @DrawableRes int drawableResId) {
Drawable drawable = ContextCompat.getDrawable(context, drawableResId);
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
} else if (drawable instanceof VectorDrawableCompat) {
return getBitmap((VectorDrawableCompat) drawable);
} else if (drawable instanceof VectorDrawable) {
return getBitmap((VectorDrawable) drawable);
} else {
throw new IllegalArgumentException("Unsupported drawable type");
}
}

}


VectorDrawableとVectorDrawableCompatの分岐部分が結構ゴリゴリやってますが、これでLollipop未満もLollipop以上も動きます。

参考 : https://github.com/konifar/droidkaigi2016/pull/349/files