iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0

終於到了重頭戲,來替我們的專案建立 Google 地圖 !

今天實作的官方文件 :

新增地圖有以下幾個基本步驟 :

  1. 在 main_activity.xml 內加入 FragmentContainer
  2. 將 SupportMapFragment 物件新增至處理地圖的 Activity。
  3. 實作 OnMapReadyCallback 介面,並取得 GoogleMap 的實例。

1. 調整 MainActivity

在開始之前,先來調整目前的畫面

  • main_activity.xml :

    先將 RecyclerView 的程式碼註解,並加入 FragmentContainer :

    <!--    <androidx.recyclerview.widget.RecyclerView-->
    <!--        android:id="@+id/recycler_view"-->
    <!--        android:layout_width="0dp"-->
    <!--        android:layout_height="wrap_content"-->
    <!--        app:layout_constraintBottom_toBottomOf="parent"-->
    <!--        app:layout_constraintEnd_toEndOf="parent"-->
    <!--        app:layout_constraintStart_toStartOf="parent"-->
    <!--        app:layout_constraintTop_toTopOf="parent"-->
    <!--        tools:listitem="@layout/item_cafe" />-->
    
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    

    目前的 main_activity.xml :

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="5dp"
        tools:context=".MainActivity">
    
        <TextView
            android:id="@+id/tv_err"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            android:textSize="16sp"
            app:layout_constraintBottom_toTopOf="@+id/button"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="GET"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    
        <ProgressBar
            android:id="@+id/progressbar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:minWidth="50dp"
            android:minHeight="50dp"
            android:visibility="invisible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <!--    <androidx.recyclerview.widget.RecyclerView-->
        <!--        android:id="@+id/recycler_view"-->
        <!--        android:layout_width="0dp"-->
        <!--        android:layout_height="wrap_content"-->
        <!--        app:layout_constraintBottom_toBottomOf="parent"-->
        <!--        app:layout_constraintEnd_toEndOf="parent"-->
        <!--        app:layout_constraintStart_toStartOf="parent"-->
        <!--        app:layout_constraintTop_toTopOf="parent"-->
        <!--        tools:listitem="@layout/item_cafe" />-->
    
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/fragment_container"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  • MainActivity 修改 initView() 程式碼,把 RecyclerView 的初始化也註解 :

    private fun initView() {
    
        adapter = MainAdapter(mutableListOf())
    
    //        binding.recyclerView.apply {
    //
    //            layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
    //            adapter = this@MainActivity.adapter
    //        }
    }
    

2. 新增 SupportMapFragment

建立 Fragment 可以分為靜態和動態,這邊直接使用動態新增 :

在 MainActivity 內的 init() 內建立 SupportMapFragment:

private fun initView() {

    adapter = MainAdapter(mutableListOf())

    // TODO: MapFragment
    val mapFragment = SupportMapFragment.newInstance()
    supportFragmentManager
        .beginTransaction()
        .add(R.id.fragment_container, mapFragment)
        .commit()
}

這邊的 fragment_container 是剛剛在 main_activity.xml 加入的 fragment 容器 FragmentContainerView

3. 實作 OnMapReadyCallback 介面,並取得 GoogleMap 的實例

class MainActivity : AppCompatActivity(), OnMapReadyCallback {

    // ...
}

覆寫 callback 的方法,以取得 GoogleMap 實例 :

override fun onMapReady(googleMap: GoogleMap) {

    googleMap.addMarker(
        MarkerOptions()
            .position(LatLng(0.0, 0.0))
            .title("Marker")
    )
}

輸入上面的經緯度會出現「空虛島」,超酷的 !

4. 動態取得權限

最後就是最重要的事情,我們需要和使用者取得權限,這邊新增 requestPermissions() :

private fun requestPermissions() {
    val REQUEST_EXTERNAL = 1;

    val PERMISSIONS_LIST = arrayOf(
        Manifest.permission.INTERNET,
        Manifest.permission.ACCESS_NETWORK_STATE,
        Manifest.permission.READ_PHONE_STATE,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_COARSE_LOCATION
    )

    var permission =
        ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
    permission += ActivityCompat.checkSelfPermission(
        this,
        Manifest.permission.ACCESS_COARSE_LOCATION
    )

    if (permission != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions(this, PERMISSIONS_LIST, REQUEST_EXTERNAL)
    }
}

onCreate() 初始化的時候,動態的和使用者取得專案需要的權限。

現在準備得差不多,來運行一下 !

d20_2.png

今日推推

Yes


上一篇
Day19 串接 Google Maps API - 設定 Google Cloud 專案與啟用 API 金鑰 (下)
下一篇
Day21 串接 Google Maps API - 在 Android 專案內使用地圖
系列文
喝咖啡要30天?一起用 Kotlin 打造尋找好喝咖啡的 App30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言