【Android 入門開發實戰:口罩地圖】Google Map 顯示目前位置

Google Map 顯示目前位置

【Android 入門開發實戰:口罩地圖】線上免費講義課程目錄

在之前的課程中,我們陸陸續續學會「如何獲取位置權限」、「如何檢查GPS是否開啟」、「如何獲取目前所在位置經緯度」和「 Google Map 基本使用方式」,綜合以上幾個單元的學習,這一節課程,我們已經可以輕鬆做出,在 Google Map 上標示並顯示目前裝置所在位置的 APP 應用程式。

將部分變數,拉出來變為全域變數

private var googleMap: GoogleMap? = null
private lateinit var mFusedLocationProviderClient: FusedLocationProviderClient

原本 getLocationPermission 寫在 onCreate ,我們將他搬到 onMapReady,代表等地圖準備好,我們再去檢查與獲取權限與位置邏輯。

override fun onMapReady(googleMap: GoogleMap) {
    this.googleMap = googleMap
    getLocationPermission()
}

在 onLocationResult 裡,將獲取到經緯度指定到 currentLocation,透過地圖的 addMarker 將所在位置標示出來,然後透過 moveCamera 將地圖畫面移動到此處。

val currentLocation =
    LatLng(
        locationResult.lastLocation.latitude,
        locationResult.lastLocation.longitude
    )
googleMap?.addMarker(
    MarkerOptions().position(currentLocation).title("現在位置")
)
googleMap?.moveCamera(
    CameraUpdateFactory.newLatLngZoom(
        currentLocation, 15f
    )
)

輸出結果

移除標記

假設裝置位置不斷在改變,但我們沒有把舊的標記清掉,就會有很多之前位置點的標記。所以我們需要加入清除上一次標記的邏輯。

private var mCurrLocationMarker: Marker? = null

...
...
...

//清除所有標記
//googleMap?.clear()

//清除上一次位置標記
mCurrLocationMarker?.remove()

//當下位置存到一個 Marker 變數中,好讓下一次可以清除
mCurrLocationMarker =googleMap?.addMarker(
    MarkerOptions().position(currentLocation).title("現在位置")
)

MarkerOptions

Markers (標記、圖釘),可以在地圖呈現一個指引圖案,吸引用戶看這裡。如圖所示:

其中 MarkerOptions 常用屬性,整理如下:

  • position:標記經緯度位置,需傳入 LatLng,此欄位必填。
  • title:標題的文字
  • snippet:片段資訊(有字數限制過程,過長會呈現…)
  • Icon :標記圖案

更多 Markers 設定可以參考官方文件: Markers

設定 Icon 圖片來源為向量圖

設定 Markers 的 Icon 圖片需為 bitmap,這裡 KT 提供一個將向量圖片轉為 bitmap 的小程式。並擴充 Int 功能,新增轉 dp 和 px 功能。

package com.thishkt.pharmacydemo.util

import android.content.Context
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.util.Log
import androidx.core.content.ContextCompat
import com.google.android.gms.maps.model.BitmapDescriptor
import com.google.android.gms.maps.model.BitmapDescriptorFactory


object ImgUtil {
    fun getBitmapDescriptor(
        context: Context,
        id: Int,
        width: Int = 0,
        height: Int = 0
    ): BitmapDescriptor? {
        val vectorDrawable: Drawable? =
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                context.getDrawable(id)
            } else {
                ContextCompat.getDrawable(context, id)
            }
        return if (vectorDrawable != null) {
            if (width == 0) vectorDrawable.intrinsicWidth
            if (height == 0) vectorDrawable.intrinsicHeight
            vectorDrawable.setBounds(0, 0, width, height)
            val bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            val canvas = Canvas(bm);
            vectorDrawable.draw(canvas);
            BitmapDescriptorFactory.fromBitmap(bm);
        } else {
            null
        }
    }

    val Int.dp: Int
        get() = (this / Resources.getSystem().displayMetrics.density).toInt()

    val Int.px: Int
        get() = (this * Resources.getSystem().displayMetrics.density).toInt()
}

向量圖片取自 Android Studio 內建的 mask 向量圖,ic_baseline_masks_24.xml

<vector android:height="24dp" android:tint="#FF5722"
    android:viewportHeight="24" android:viewportWidth="24"
    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="@android:color/white" android:pathData="M19.5,6c-1.31,0 -2.37,1.01 -2.48,2.3C15.14,7.8 14.18,6.5 12,6.5c-2.19,0 -3.14,1.3 -5.02,1.8C6.87,7.02 5.81,6 4.5,6C3.12,6 2,7.12 2,8.5V9c0,6 3.6,7.81 6.52,7.98C9.53,17.62 10.72,18 12,18s2.47,-0.38 3.48,-1.02C18.4,16.81 22,15 22,9V8.5C22,7.12 20.88,6 19.5,6zM3.5,9V8.5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v3c0,1.28 0.38,2.47 1.01,3.48C4.99,14.27 3.5,12.65 3.5,9zM20.5,9c0,3.65 -1.49,5.27 -3.01,5.98c0.64,-1.01 1.01,-2.2 1.01,-3.48v-3c0,-0.55 0.45,-1 1,-1s1,0.45 1,1V9zM10.69,10.48c-0.44,0.26 -0.96,0.56 -1.69,0.76V10.2c0.48,-0.17 0.84,-0.38 1.18,-0.58C10.72,9.3 11.23,9 12,9s1.27,0.3 1.8,0.62c0.34,0.2 0.71,0.42 1.2,0.59v1.04c-0.75,-0.21 -1.26,-0.51 -1.71,-0.78C12.83,10.2 12.49,10 12,10C11.51,10 11.16,10.2 10.69,10.48z"/>
</vector>

MarkerOptions 設定參數

googleMap?.addMarker(
    MarkerOptions()
        .position(currentLocation).title("現在位置")
        .snippet("這裡可以顯示相關資訊,太過長會被截掉").icon(
            getBitmapDescriptor(
                mContext,
                R.drawable.ic_baseline_masks_24,
                60.px,
                60.px
            )
        )
)

輸出結果

地圖開啟預設位置

在 onMapReady 加入移動鏡頭到預設座標位置,這樣開啟時預設就會先看到此位置。

//台北101
private val defaultLocation = LatLng(25.0338483, 121.5645283)
...
...
...
override fun onMapReady(googleMap: GoogleMap) {
      ...
      
        googleMap.moveCamera(
            CameraUpdateFactory.newLatLngZoom(
                defaultLocation, 6f
            )
        )
    }

預設開啟資訊視窗

Marker 有一個 showInfoWindow 方法,即可在不用點任何標記下,預設開啟此標記的資訊視窗。

currLocationMarker?.showInfoWindow()

目前所在位置,使用預設藍色小點呈現

googleMap?.isMyLocationEnabled = true

輸出結果

參考資料

Select Current Place and Show Details on a Map
https://developers.google.com/maps/documentation/android-sdk/current-place-tutorial

MapsActivityCurrentPlace.kt
https://github.com/googlemaps/android-samples/blob/bb1492036ad171443f549054c7e750dfe1a5cc64/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.kt

程式碼範例

範例名稱:Google Map 顯示目前位置
開發人員:HKT (侯光燦)
程式語言:Kotlin
開發環境:Android Studio 4.1.2 & Android 11 & Kotlin 1.4.30
授權範圍:使用時必須註明出處且不得為商業目的之使用
範例下載點:點我下載

範例名稱:清除標記
開發人員:HKT (侯光燦)
程式語言:Kotlin
開發環境:Android Studio 4.1.2 & Android 11 & Kotlin 1.4.30
授權範圍:使用時必須註明出處且不得為商業目的之使用
範例下載點:點我下載

範例名稱:目前所在位置,使用預設藍色小點呈現
開發人員:HKT (侯光燦)
程式語言:Kotlin
開發環境:Android Studio 4.1.2 & Android 11 & Kotlin 1.4.30
授權範圍:使用時必須註明出處且不得為商業目的之使用
範例下載點:點我下載

這個網誌中的熱門文章

2023 最新入門零基礎 Kotlin教學【從零開始學 Kotlin 程式設計】Kotlin 教學課程目錄 (Android Kotlin, IntelliJ IDEA, Android Studio, Android APP 開發教學)

nano 文字編輯器

2022 最新入門零基礎 Flutter教學 【Flutter 程式設計入門實戰 30 天】Flutter 教學課程目錄 (IntelliJ IDEA 開發教學)

16天記下7000單字

最新入門零基礎 Java 教學【從零開始學 Java 程式設計】Java教學課程目錄 (IntelliJ IDEA 開發教學)