【Android 入門開發實戰:口罩地圖】Google Map 自訂資訊視窗

 

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

在上一節課,我們使用了 Google Map 官方預設的資訊視窗,真的很簡潔,很方便立刻上手使用,但相對顯示較陽春。若我們想要顯要顯示更多資訊內容,可以透過自定義資訊視窗來解決這個問題。

自定義資訊視窗佈局

在 layout 資料夾新增 info_window.xml,跟RecyleView 佈局一樣,但因為資訊視窗關係,因為沒有 parent 可以對齊寬度和高度,所以不能採用 match_parent ,需要設定一個大小或根據內容決定整體寬度和高度大小。所以佈局相似,但我們需修改一下相關設定。完整細節如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginTop="10dp"
    android:layout_marginRight="10dp"
    app:cardCornerRadius="8dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/layout_item"
        android:layout_width="300dp"
        android:layout_height="150dp"
        android:background="?android:attr/selectableItemBackground"
        android:clickable="true"
        android:focusable="true"
        android:paddingBottom="20dp">


        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="15dp"
            android:text="藥局名稱"
            android:textColor="#424242"
            android:textSize="30dp"
            app:layout_constraintBottom_toTopOf="@+id/layout_adult"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/layout_adult"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_amount_info"
            android:padding="10dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/layout_child"
            app:layout_constraintTop_toBottomOf="@+id/tv_name">

            <TextView
                android:id="@+id/tv_adult"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="成人口罩"
                android:textColor="#ffffff"
                android:textSize="20dp"
                android:textStyle="bold"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/tv_adult_amount"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="口罩數量"
                android:textColor="#ffffff"
                android:textSize="16dp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_adult" />
        </androidx.constraintlayout.widget.ConstraintLayout>

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/layout_child"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_amount_info"
            android:padding="10dp"
            app:layout_constraintLeft_toRightOf="@+id/layout_adult"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tv_name">

            <TextView
                android:id="@+id/tv_child"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="小孩口罩"
                android:textColor="#ffffff"
                android:textSize="20dp"
                android:textStyle="bold"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/tv_child_amount"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="口罩數量"
                android:textColor="#ffffff"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_child" />
        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

自定義 InfoWindowAdapter

新增 MyInfoWindowAdapter.kt 覆寫實作 GoogleMap.InfoWindowAdapter 的方法:

package com.thishkt.pharmacydemo.adapter

import android.app.Activity
import android.content.Context
import android.view.View
import android.widget.TextView
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.Marker
import com.thishkt.pharmacydemo.R

class MyInfoWindowAdapter(context: Context) : GoogleMap.InfoWindowAdapter {

    var mWindow: View = (context as Activity).layoutInflater.inflate(R.layout.info_window, null)

    private fun render(marker: Marker, view: View) {

        val tvName = view.findViewById<TextView>(R.id.tv_name)
        val tvAdultAmount = view.findViewById<TextView>(R.id.tv_adult_amount)
        val tvChildAmount = view.findViewById<TextView>(R.id.tv_child_amount)

        val mask = marker.snippet.toString().split(",")

        tvName.text = marker.title
        tvAdultAmount.text = mask[0]
        tvChildAmount.text = mask[1]

    }

    override fun getInfoContents(marker: Marker): View {
        render(marker, mWindow)
        return mWindow
    }

    override fun getInfoWindow(marker: Marker): View? {
        return null
    }
}

設定 InfoWindowAdapter

最後設定我們的地圖 googleMap ,載入我們自定義的資訊視窗。

currLocationMarker?.remove()
googleMap?.setInfoWindowAdapter(MyInfoWindowAdapter(mContext))
currLocationMarker = googleMap?.addMarker(
    MarkerOptions()
        .position(currentLocation)
        .title("現在位置")
        .snippet("100,66")
)
currLocationMarker?.showInfoWindow()

輸出結果

資訊視窗點擊事件

加入 setOnInfoWindowClickListener 處理事件

googleMap?.setOnInfoWindowClickListener {
    Log.d(
        "HKT",
        "title: ${currLocationMarker?.title}"
    )
}

程式碼範例

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

這個網誌中的熱門文章

16天記下7000單字

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

nano 文字編輯器

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

【從零開始學 Flutter 程式設計】SharedPreferences 設定檔資料存取