iT邦幫忙

2025 iThome 鐵人賽

DAY 22
0
Mobile Development

《30 天 Flutter:跨平台 AI 行程規劃 App》系列 第 22

Day 22 - 行程 APP 沒地圖怎麼行?從零打造地圖互動功能,試試 ChatGPT 的教學體驗

  • 分享至 

  • xImage
  •  

今天不知道 Gemini 怎麼了,突然直接噴 500 錯誤,原本想靠它來學習 Google Map 套件。既然不給力,就乾脆跳槽到 ChatGPT 吧!剛好最近它也推出了「學習模式」,正好拿來比較一下實際使用體驗。

以下是我在 ChatGPT 學習模式下丟的 Prompt:

幫我閱讀這幾個網址連結
https://pub.dev/packages/google_maps_flutter
https://developers.google.com/maps/flutter-package/overview?hl=zh-tw
https://github.com/flutter/plugins/tree/main/packages/google_maps_flutter
從 0 開始教我使用 google_maps_flutter,目標是在我的應用程式添加這兩個功能:

  1. 學會放 Marker(對應行程中的景點)。
  2. 學會 Camera 移動(行程列表 → 點景點 → 地圖移動到該地點)。

套件簡介

google_maps_flutter 是 Google 官方維護的 Flutter plugin,本質上是把 原生的 Google Maps SDK(Android / iOS)包裝成 Flutter widget,讓我們在 Flutter 裡也能用到原生地圖的能力。

它的特色包括:

  • 互動地圖:支援縮放、拖曳。
  • 地圖標記:可以放置 Marker、Polyline、Polygon(景點、路線、區域)。
  • Camera 控制:移動畫面到指定座標、縮放。
  • 事件回呼:點擊地圖或 Marker 時能觸發事件。
  • 原生渲染:Android / iOS SDK 驅動 → 效能優於 WebView。

取得 Google Maps API Key

  1. 進入 Google Cloud Console
  2. 建立一個專案(或使用現有的)。
  3. 在左側選單 → API 和服務+ 啟用 API 與服務
  4. 啟用 Maps SDK for AndroidMaps SDK for iOS
    • 需要綁信用卡。
    • 建議在金鑰設定中限制使用範圍(例如:限定 Android App + iOS App)。
  5. 產生 API Key 並複製下來。

安裝與設定

安裝套件

dependencies:
  google_maps_flutter: ^2.13.1

Android 設定

android/app/src/main/AndroidManifest.xml<application> 內加入:

<manifest ...
  <application ...
    <meta-data android:name="com.google.android.geo.API_KEY"
           android:value="你的_API_KEY" />

注意事項:

  • Google Play 服務
    • 實體機必須安裝 Google Play 服務,否則無法顯示地圖。
    • 模擬器需選擇「Google Play enabled」的版本,選擇帶有「Google Play」標籤的映像(例:Android 13 (Google Play))。
  • 網路連線:需要上網才能載入地圖。

iOS 設定

ios/Runner/AppDelegate.swift 中,於 didFinishLaunchingWithOptions 加入:

import GoogleMaps   // 記得要 import

GMSServices.provideAPIKey("你的_API_KEY")

完整範例:

import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GMSServices.provideAPIKey("你的_API_KEY")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

確認 ios/Podfile 的版本:

platform :ios, '14.0'

若低於 14.0 會出現不相容的錯誤。

再接著執行:

cd ios
pod install

測試地圖能否跑起來

先跑一個簡單的 GoogleMap widget,如果能看到地圖(不是灰色背景或「API key invalid」),就代表設定成功。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: MapSample());
  }
}

class MapSample extends StatefulWidget {
  const MapSample({super.key});

  @override
  State<MapSample> createState() => MapSampleState();
}

class MapSampleState extends State<MapSample> {
  final Completer<GoogleMapController> _controller = Completer();

  static const CameraPosition _kInitialPosition = CameraPosition(
    target: LatLng(25.033964, 121.564468), // 台北 101
    zoom: 14.0,
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Google Map 測試")),
      body: GoogleMap(
        initialCameraPosition: _kInitialPosition,
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },
      ),
    );
  }
}

效果如下:

Android iOS

常用功能

CameraPosition (相機位置)

控制地圖的顯示範圍與角度。

主要參數:

  • targetLatLng(latitude, longitude),地圖的中心點座標。
  • zoom:縮放層級 (數字越大越近,一般 14 ~ 16 適合市區,18 以上適合街景等級)。
  • bearing:地圖旋轉角度(0 = 正北)。
  • tilt:傾斜角度,0 表示俯視,越大越有 3D 效果。

範例:

static const CameraPosition _kTokyo = CameraPosition(
  target: LatLng(35.6804, 139.7690), // 東京站
  zoom: 16,
  bearing: 30,
  tilt: 45,
);

Marker (標記點)

在地圖上標記一個地點(常見於餐廳、景點定位)。

主要參數:

  • markerId:每個標記需要一個唯一 ID。
  • position:標記的位置 (LatLng)。
  • infoWindow:點擊標記後顯示的視窗(標題、副標題)。
  • icon:自訂圖示(可用 BitmapDescriptor)。
    • icon: BitmapDescriptor.defaultMarker,,這會產生紅色的標準 Google Maps 標記。
  • onTap:點擊標記時的 callback。

範例:

Marker(
  markerId: const MarkerId("taipei101"),
  position: const LatLng(25.033964, 121.564468),
  infoWindow: const InfoWindow(title: "台北 101", snippet: "著名地標"),
  icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueAzure),
);

Polyline (路徑線條)

用於繪製路線(例如導航路徑)。

主要參數:

  • polylineId:唯一 ID。
  • points:路徑的座標點列表。
  • color:線條顏色。
  • width:線條寬度。
  • patterns:虛線、點線效果。

範例:

Polyline(
  polylineId: const PolylineId("route1"),
  points: const [
    LatLng(25.033964, 121.564468), // 台北 101
    LatLng(25.047924, 121.517081), // 台北車站
  ],
  color: Colors.blue,
  width: 5,
);

GoogleMap 常見參數

GoogleMap Widget 裡可以設定:

  • markersSet<Marker>,放置多個標記。
  • polylinesSet<Polyline>,顯示多條路線。
  • myLocationEnabled:顯示使用者當前位置(需權限)。
  • zoomControlsEnabled:是否顯示縮放按鈕。
  • mapType:地圖型態。
    • normal:標準地圖,日常導航常用
    • satellite:衛星影像,適合戶外探勘
    • terrain:顯示等高線與地形,適合登山與地理用途
    • hybrid:衛星影像加上道路與地名,適合旅遊與展示

ChatGPT 與 Gemini 的比較心得

在學習模式上,ChatGPT 和 Gemini 各有特色,也各有優缺點。

互動風格差異

  • Gemini:比較「循序漸進」,會等你一步步提問。如果問題問得太發散,它會主動把你拉回正題,避免偏離學習目標。
  • ChatGPT:屬於「一次丟出大量資訊」的類型,細節比 Gemini 多,會預判可能的錯誤。不過它也容易順著你的話題延伸,有時會整段偏題。例如我隨口問:「Google Play 服務是不是代表中國手機可能無法使用?」結果 ChatGPT 直接反問我:「你的 App 打算只在台灣/海外用,還是要進中國市場?」──以我的個性來說,蠻容易被帶偏的。

細節與準確度

兩者在細節上偶爾仍會出錯。像今天 ChatGPT 說 ios/Podfile 的版本只要 13.0 以上,實際上要 14.0 以上才行;取得 Google Maps API Key 的流程也有小差異需要留意。

綜合建議

整體來說,ChatGPT 和 Gemini 都能提供結構完整的教學,特別適合「從零開始」的學習過程。選哪一個,可以依照你的學習習慣:

  • 喜歡被動引導、循序漸進 → Gemini
  • 習慣一次吸收大量資訊 → ChatGPT

兩者我都蠻推薦的,但我個人會用 Gemini ~


上一篇
Day 21 - 從單機到分享:讓旅伴也能擁有這份完美行程
系列文
《30 天 Flutter:跨平台 AI 行程規劃 App》22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言