🎅

Maps SDK for Android のマーカーを任意の色で表示する

2022/12/24に公開

この記事はLuup Advent Calendarの24日目の記事です。

こんにちは、Androidチームに業務委託として所属しているIshizakiです。

気がついたら今年も残り1週間。このアドベントカレンダーも残すところ2日となりました。
本日はAndroidアプリ開発の中でも Maps SDK for Android のマーカーをカラフルに生成するという何ともニッチなお話なのですが、地図マーカーに限らず使える部分もあるのでご一読いただけたら幸いです。

LUUPの地図画面とマーカーについて

ご存知の通りLUUPアプリはその大半において地図画面が表示されます。

そして地図上には無数のポートを示すマーカーが存在します。
地図画面

マーカーは現在の仕様では緑、黄色、グレーの3色となっています。
LUUPのポートアイコン

3色のマーカーの出し分け

先ほどの地図上に表示されたマーカーですが、これら1つ1つの情報はサーバーから受信しています。
その情報の中には、例えばポートの名前や所在地(緯度経度)だとか、そのポートに何台停められて現在何台停まっているのか、営業時間やキャンペーン有無など様々な情報が含まれています。

クライアントアプリではこれらの情報を元に各ポートの状態(利用可 or キャンペーン中 or 利用不可)を判定してマーカー色を確定し、その出し分けには緑・黄色・グレーのSVGファイルを使い分けています。

そのため、新しい色のマーカーを出すには新しい色のSVGファイルを用意してそれを取り込んだクライアントアプリを作るしかありません。

そこでポート情報の中に色情報(RGB値)を追加することで、サーバーから指定された色でポートマーカーを表示できないか、という話が浮上しました。

以下の検証結果は技術的には実現に至ったものの、現時点では新しい色のマーカーを出す予定がない等、諸々の事情からLUUPアプリでは採用を見送りました。

任意のRGB色にマーカーの色を変更

SVGファイルを任意の色に変えるには、まずSVGファイルからdrawableを生成して、Drawable#setTint(int)で着色すればよさそうです。

ただ、setTintで色が変わるのは不透過部分です。LUUPアプリで使っているポートマーカーは透過部分(画像内の細かいチェック柄部分)、白色部分、カラー部分があり、普通にsetTintすると白色部分とカラー部分がまとめて変わってしまいます。
失敗例

そのため意図通りに変色させるには土台となる白色画像と可変色部分のみの画像を用意して、後者を変色した後に土台と重ね合わせるという作業が必要になります。
ロードマップ

画像の重ね合わせとマーカーの生成

画像の重ね合わせというとCanvasクラスとかでBitmapを生成してゴリゴリと重ね合わせる、みたいなことを考えがちなのですが、Androidには複数のdrawableを重ねてくれるLayerDrawableというクラスが存在します。

このクラスは意外と知られてない気がするのですが、このように複数のdrawableが簡単に合成できるのでとても便利です。

val newDrawable = LayerDrawable(arrayOf(drawable1, drawable2, drawable3 …))

LayerDrawableクラスはDrawableクラスを継承しているのでマーカー生成に必要なBitmapDescriptorへの変換も簡単にできます。

ランダムな色でマーカーを表示

せっかくなのでポート毎にランダムな色を割り振ってみました。今日はクリスマスイブということで赤系と緑系に色を寄せています。
これで1枚のSVG画像から無数の色のマーカーが生成できました。

ランダム色マーカー

おわりに

以上が Maps SDK for Android のマーカーを任意の色で表示する流れです。
複数画像の重ね合わせ処理は Maps SDK のマーカーに限らずいろいろな場面で使用でき、うまく活用することでリソース量を軽減できたりもします。

LUUPアプリは地図画面が重要な役割のを担っているので Maps SDK の探求は今後も続けていきます。
また何か面白い情報がありましたらこちらで紹介したいと思います。

最後までお読みいただきありがとうございました。
明日はいよいよ最終日!
CTO岡田さんがラストを締めくくります!

Luup Developers Blog

Discussion