Day 28:Google Map 显示目前位置

本篇文章同步发表在 HKT 线上教室 部落格,线上影音教学课程已上架至 UdemyYoutube 频道。另外,想追踪更多相关技术资讯,欢迎到 脸书粉丝专页 按赞追踪喔~

程序码范例

范例名称: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
授权范围:使用时必须注明出处且不得为商业目的之使用
范例下载点:点我下载

在之前的介绍当中,我们陆陆续续学会「如何获取位置权限」、「如何检查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

输出结果

参考资料

HKT 线上教室
https://tw-hkt.blogspot.com/

Freepik
https://www.freepik.com/

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


那今天【iThome 铁人赛】就介绍到这边罗~

顺带一提,KT 线上教室,脸书粉丝团,会不定期发布相关资讯,不想错过最新资讯,不要忘记来按赞,追踪喔!也欢迎大家将这篇文章分享给更多人喔。

我们明天再见罗!!!掰掰~


<<:  Turbo Pascal 语言和你 SAY HELLO!!

>>:  Day 13 Mailhog - 模拟 SMTP 邮件服务的开发利器

[第二十六天]从0开始的UnityAR手机游戏开发-输出64位元的APP

点开Project Settings的other,把Scripting Backend改为IL2CP...

在Heroku一键架好Ubuntu,并用浏览器配noVNC连进去

更多会员限定文章可以到patreon观看 可以用现成的Dockerfile会更快 (包含一键布署) ...

Day9 javascript 条件语句

JavaScript 条件语句基於不同的条件来执行不同的动作,通常在写代码时,总是需要为不同的决定来...

如何修复无法在Windows 10中创建恢复磁碟机的错误

Windows 10允许您创建复原磁碟机,以便您可以使用该装置将Windows 10复原到以前的日期...

OpenCart 4.0 内建一页式结帐

今天稍微测试了一下 OpenCart 4.0,很多地方不同於 OpenCart 3,之前光是看到规格...