省エネエンジニア

ゆるっとエンジニアやってます。働きたくない系エンジニア。Android、Webのお仕事やってます。

【Android】GoogleMapApiを使ったのでログ

こんにちは。 今年最後のブログを書こうと思います。

12月中は常駐のお仕事を一旦お休みしてだらだら生活を送ろうと思ってたのに、 ひょんなことからGoogleMapを使うお仕事をいただいてしまったので、 結局キリキリ働いていました。

GoogleMapApiを使ったのでどんなことをしたかログを残そうと思います。

まずは導入。

1、Apiキーの取得

API キーの取得  |  Google Maps Android API  |  Google Developers

ここからApiキーを取得する必要があります。

2、アプリの設定。

一番簡単な方法は、Projectを作成する時にGoogleMapActivityを選択することですね。 これを選択してprojectを作ると下のコードは作成済みの状態になります。

f:id:qkuroneko:20171230111204p:plain

AndroidManifest.xml

    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_maps_key"/>

Manifestの<application></application>に上のようにApiキーを設定します。

実際にMapが表示されるレイアウトはこんな感じです。

activity_map.xml

    <fragment
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.linkbal.together.together_android.view.map.MapsActivity"
        />

今回はSupportMapFragmentを使いました。

MapActivity.kt

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions

class MapActivity : AppCompatActivity(), OnMapReadyCallback {

    private lateinit var mMap: GoogleMap

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_maps)
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        val mapFragment = supportFragmentManager
                .findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }
    
    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap

        // Add a marker in Sydney and move the camera
        val sydney = LatLng(-34.0, 151.0)
        mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
        mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
    }
}

ここまでできたらもう地図を表示する事が可能です。

f:id:qkuroneko:20171230114120p:plain:w300

mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney")) これで、地図上にマーカーを追加する事ができます。 マーカーは複数追加できるみたいです。

mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)) これで、設定した位置情報が中心にくるようにカメラが移動します。

4、カスタマイズ

今回のお客様のご要望により、このマーカーを自分の用意した画像に変更したいとのことです。

こうします。

mMap.addMarker(MarkerOptions()
        .position(sydney)
        .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher))
        .title("Marker in Sydney")

.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher)) ここですね。

すると、ごらんの通り。

f:id:qkuroneko:20171230122025p:plain:w300

お次のご要望としては、1kmの円を描きたいとの事。

 mMap.addCircle(CircleOptions()
         .center(sydney)
         .radius(500.0)
         .strokeWidth(5f)
         .strokeColor(ContextCompat.getColor(applicationContext, R.color.colorCircleStroke))
         .fillColor(ContextCompat.getColor(applicationContext, R.color.colorCircleFill))
         .clickable(false)
)

こうします。

すると、こう。

f:id:qkuroneko:20171230150046p:plain:w300

さて、このマーカーをタップした時の反応は、デフォルトだとこうなります。 .title("Marker in Sydney")に設定している文字が吹き出しで出てきます。

f:id:qkuroneko:20171230150442p:plain:w300

今回のご要望だと、ここをカスタマイズしたいとのこと。

そんなときはこうじゃっ!

class MapInfoAdapter : InfoWindowAdapter {

    override fun getInfoContents(marker: Marker?): View {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun getInfoWindow(marker: Marker?): View {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

InfoWindowAdapterを継承したadapterクラスを作ります。

ここにlayoutをinfrateすれば吹き出しをカスタマイズできます。 getInfoWindowは表示される枠全てがinfrateされます。 getInfoContentsは吹き出しの中だけがinftateされます。 デザインに合わせてどちらを使うかを決めてください。

mMap.setInfoWindowAdapter(MapInfoAdapter())

あとは、このadapterをsetするだけ。 簡単!

これくらいならApiの機能を使って簡単に実装できたのですが、 実際はもっと色々カスタマイズしたいとのご要望をいただいていて、 結構工夫を凝らさないとできない事があったのですが、 酔っ払ってきたのでこの辺で終わりにします。

また、年明けに続きを書くかもしれません。

それでは、良いお年を。