在地圖上最常見的物件就是 Marker
(官方翻譯為標記),在地圖上它代表的是一個點的位置,所以它所關聯的空間資訊就是經緯度。
話不多說,就讓我們進到實際製作的階段吧。
還記得前面兩天的 TileOverlay
都是透過TileOverlayOptions
來設定,並透過 addTileOverlay()
來加入到 GoogleMap
上。
Marker
概念上也是如此。
Marker
的樣式。GoogleMap.addMarker()
用這個方法在地圖上建立 Marker
。private var googleMap: GoogleMap? = null
private var simpleMarker: Marker? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.mapView.onCreate(savedInstanceState)
binding.mapView.getMapAsync {
// 略...
simpleMarker = addSimpleMarker(it)
}
}
/**
* 加入基本款的標記到地圖並取得 Marker 物件
*
* @param map
* @return Marker
*/
private fun addSimpleMarker(map: GoogleMap): Marker? {
val taichungOpera = LatLng(24.1627, 120.6403)
return map.addMarker(
MarkerOptions()
.position(taichungOpera)
)
}
跟 TileOverlay
一樣,呼叫 Marker
中的 remove()
方法,即可將 Marker
從地圖上移除。
simpleMarker?.remove()
Marker
的 Icon 除了預設的紅色外,還有其他顏色可以設定。
不過在那之前,要先知道,Marker
的 Icon 樣式是透過 MarkerOptions().icon()
來做設定。icon()
所需要傳入的 BitmapDescriptor
參數,則可以透過 BitmapDescriptorFactory
。
像是以下的範例,會是在台中中央公園的點位上,加上一個藍色的 Marker
。
private fun addBlueMarkers(map: GoogleMap) {
val centralPark = LatLng(24.1858, 120.6533)
map.addMarker(MarkerOptions()
.position(centralPark)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))
)
}
除了 BitmapDescriptorFactory.HUE_BLUE
(藍色) 外,還有其他種顏色可選。
如果都沒有喜歡的,沒關係,明天的客製化 Marker
會聊到如何自定義。
除了調整 Marker
的圖示外,透過 MarkerOptions()
的 title()
跟 snippet()
,可以讓 Marker
在點擊時,在 Marker
上方出現一個小資訊視窗。
private fun addMarkerWithInfo(map: GoogleMap) {
val university = LatLng(24.1789, 120.6464)
map.addMarker(MarkerOptions()
.position(university)
// 黑體標題
.title("逢甲大學")
// 灰體副標題
.snippet("${university.latitude} , ${university.longitude}")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
)
}
除了預設的 UI,也是可以透過 InfoWindowAdapter 自定如下方的 InfoWindow。
圖片來源:官方文件
但以我自己的經驗,實務上比較少使用這個 API,反而圖標上的資訊通常會搭配其他客製化 UI,如 BottomSheet
或 Dialog
來呈現。
有興趣的人可以參考官方文件的說明與範例,如果有遇到問題,也歡迎在下方留言區討論~
GoogleMap.OnMarkerClickListener
點擊事件指的是使用者點擊 Marker
所觸發的事件,實際的實作方式如下。
點擊事件的監聽是設定在 GoogleMap
之上,意味著所有的 Marker
的點擊事件都會透過這個 OnMarkerClickListener.onMarkerClick(marker): Boolean
傳出。
// 設定地圖的 Marker 點擊事件監聽
map.setOnMarkerClickListener { clickedMarker ->
// 將被點擊的 Marker 的標題與經緯度取出並用 Toast 顯示
Toast.makeText(
this@MarkerActivity,
"${clickedMarker.title} / ${clickedMarker.position.latitude} , ${clickedMarker.position.longitude}",
Toast.LENGTH_LONG
).show()
// 回傳 false 表示點擊事件會繼續傳遞,讓 SDK 執行預設的行為
return@setOnMarkerClickListener false
}
這個點擊事件要特別注意的事情是,當 onMarkerClicked()
的回傳值設為
true
: 代表點擊事件會完全由我們處理,預設的 Marker
點擊行為不會被觸發。false
: 反之,預設的 Marker
行為會按照預設的模式執行。預設的點擊行為:地圖將 Marker 移至目前視窗的中心,如有 InfoWindow 則會顯示。
到目前為止所介紹的 Marker
都是固定在特定點位,而可拖曳的 Marker
是可以讓使用者長按並移動它在地圖上的位置。
以下範例,我們建立了一個位在台中青海家樂福的綠色 Marker
,並使用 draggable(true)
讓 Marker
可以被拖曳。
private fun addDraggableMarker(map: GoogleMap) {
val carrefour = LatLng(24.1702, 120.6447)
map.addMarker(
MarkerOptions()
.position(carrefour)
.draggable(true)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))
)
}
這個拖曳功能比較常見的應用,就是讓使用者在圖面上標記經緯度。
跟點擊事件一樣,拖曳事件的監聽一樣是設定在 GoogleMap
上,透過 setOnMarkerDragListener()
加入 OnMarkerDragListener
介面負責監聽。
map.setOnMarkerDragListener(object : OnMarkerDragListener{
override fun onMarkerDrag(marker: Marker) {
// Marker 移動中
Log.d(TAG, "onMarkerDrag: 移動中")
}
override fun onMarkerDragEnd(marker: Marker) {
// Marker 移動結束
Toast.makeText(
this@MarkerActivity,
"Marker 移動結束",
Toast.LENGTH_SHORT
).show()
}
override fun onMarkerDragStart(marker: Marker) {
// Marker 開始移動
Toast.makeText(
this@MarkerActivity,
"Marker 移動開始",
Toast.LENGTH_SHORT
).show()
}
})
以上就是基本款的 Marker
設定與常見的互動事件,明天我們會接著看 Marker
的客製化。
那就一樣,明天見啦~