افزودن Google Maps به برنامه Flutter

۱. مقدمه

فلاتر (Flutter) کیت توسعه نرم‌افزار (SDK) اپلیکیشن موبایل گوگل است که برای ساخت تجربه‌های بومی با کیفیت بالا در iOS و اندروید در کمترین زمان ممکن طراحی شده است.

با افزونه Google Maps Flutter ، می‌توانید نقشه‌هایی را بر اساس داده‌های نقشه‌های گوگل به برنامه خود اضافه کنید. این افزونه به طور خودکار دسترسی به سرورهای نقشه‌های گوگل، نمایش نقشه و پاسخ به حرکات کاربر مانند کلیک‌ها و کشیدن‌ها را مدیریت می‌کند. همچنین می‌توانید نشانگرهایی را به نقشه خود اضافه کنید. این اشیاء اطلاعات اضافی برای مکان‌های نقشه ارائه می‌دهند و به کاربر اجازه می‌دهند با نقشه تعامل داشته باشد.

آنچه خواهید ساخت

در این آزمایشگاه کد، شما یک برنامه موبایل با نقشه گوگل با استفاده از Flutter SDK خواهید ساخت. برنامه شما:

  • نمایش نقشه گوگل
  • بازیابی داده‌های نقشه از یک سرویس وب
  • این داده‌ها را به صورت نشانگر روی نقشه نمایش دهید

اسکرین‌شاتی از یک برنامه Flutter با نقشه گوگل که در یک شبیه‌ساز آیفون با نمای کوهستانی هایلایت شده اجرا می‌شود

فلاتر چیست؟

فلاتر سه قابلیت اصلی دارد.

  • توسعه سریع : برنامه‌های اندروید و iOS خود را در عرض چند میلی‌ثانیه با Stateful Hot Reload بسازید.
  • رسا و انعطاف‌پذیر : ارائه سریع ویژگی‌ها با تمرکز بر تجربیات بومی کاربر نهایی.
  • عملکرد بومی در iOS و اندروید : ویجت‌های فلاتر تمام تفاوت‌های اساسی پلتفرم - مانند پیمایش، ناوبری، آیکون‌ها و فونت‌ها - را در خود جای داده‌اند تا عملکرد بومی کاملی را ارائه دهند.

نقشه‌های گوگل دارای موارد زیر است:

  • پوشش ۹۹٪ از جهان : با داده‌های جامع و قابل اعتماد برای بیش از ۲۰۰ کشور و منطقه ساخته شده است.
  • ۲۵ میلیون به‌روزرسانی روزانه : روی اطلاعات مکانی دقیق و بلادرنگ حساب کنید.
  • ۱ میلیارد کاربر فعال ماهانه : با اطمینان خاطر و با پشتیبانی زیرساخت‌های گوگل مپس، مقیاس‌پذیری بالایی دارد.

این آزمایشگاه کدنویسی شما را در ایجاد یک تجربه نقشه‌های گوگل در یک برنامه Flutter برای iOS و اندروید راهنمایی می‌کند.

آنچه یاد خواهید گرفت

  • نحوه ایجاد یک برنامه جدید Flutter.
  • نحوه پیکربندی افزونه Google Maps Flutter.
  • نحوه اضافه کردن نشانگرها به نقشه، با استفاده از داده‌های موقعیت مکانی از یک سرویس وب.

این آزمایشگاه کد بر افزودن نقشه گوگل به یک برنامه فلاتر تمرکز دارد. مفاهیم و بلوک‌های کد نامربوط نادیده گرفته شده‌اند و برای کپی و پیست ساده در اختیار شما قرار گرفته‌اند.

دوست دارید از این آزمایشگاه کد چه چیزهایی یاد بگیرید؟

من تازه وارد این مبحث شدم و یه دید کلی و جامع می‌خوام. من یه چیزایی در مورد این موضوع می‌دونم، اما می‌خوام یه مرور کلی بکنم. دنبال یه نمونه کد هستم که تو پروژه ام ازش استفاده کنم. دنبال توضیح یه چیز خاص هستم.

۲. محیط فلاتر خود را تنظیم کنید

برای تکمیل این آزمایشگاه به دو نرم‌افزار نیاز دارید: SDK فلاتر و یک ویرایشگر . این آزمایشگاه کد، اندروید استودیو را در نظر می‌گیرد، اما شما می‌توانید از ویرایشگر دلخواه خود استفاده کنید.

شما می‌توانید این codelab را با استفاده از هر یک از دستگاه‌های زیر اجرا کنید:

  • یک دستگاه فیزیکی (اندروید یا iOS) که به رایانه شما متصل شده و روی حالت توسعه‌دهنده تنظیم شده باشد.
  • شبیه‌ساز iOS (نیاز به نصب ابزارهای Xcode دارد.)
  • شبیه‌ساز اندروید (نیاز به راه‌اندازی در اندروید استودیو دارد.)

۳. شروع کار

شروع کار با فلاتر

ساده‌ترین راه برای شروع کار با Flutter استفاده از ابزار خط فرمان flutter برای ایجاد تمام کدهای مورد نیاز برای یک تجربه شروع ساده است.

$ flutter create google_maps_in_flutter --platforms android,ios,web
Creating project google_maps_in_flutter...
Resolving dependencies in `google_maps_in_flutter`... 
Downloading packages... 
Got dependencies in `google_maps_in_flutter`.
Wrote 81 files.

All done!
You can find general documentation for Flutter at: https://docs.flutter.dev/
Detailed API documentation is available at: https://api.flutter.dev/
If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev

In order to run your application, type:

  $ cd google_maps_in_flutter
  $ flutter run

Your application code is in google_maps_in_flutter/lib/main.dart.

افزودن افزونه Google Maps Flutter به عنوان یک وابستگی

افزودن قابلیت‌های اضافی به یک برنامه Flutter با استفاده از بسته‌های Pub آسان است. در این آزمایشگاه کد، افزونه Google Maps Flutter را با اجرای دستور زیر از دایرکتوری پروژه معرفی می‌کنید.

$ cd google_maps_in_flutter
$ flutter pub add google_maps_flutter
Resolving dependencies... 
Downloading packages... 
+ csslib 1.0.0
+ flutter_plugin_android_lifecycle 2.0.19
+ flutter_web_plugins 0.0.0 from sdk flutter
+ google_maps 7.1.0
+ google_maps_flutter 2.6.1
+ google_maps_flutter_android 2.8.0
+ google_maps_flutter_ios 2.6.0
+ google_maps_flutter_platform_interface 2.6.0
+ google_maps_flutter_web 0.5.7
+ html 0.15.4
+ js 0.6.7 (0.7.1 available)
+ js_wrapping 0.7.4
  leak_tracker 10.0.4 (10.0.5 available)
  leak_tracker_flutter_testing 3.0.3 (3.0.5 available)
  material_color_utilities 0.8.0 (0.11.1 available)
  meta 1.12.0 (1.14.0 available)
+ plugin_platform_interface 2.1.8
+ sanitize_html 2.1.0
+ stream_transform 2.1.0
  test_api 0.7.0 (0.7.1 available)
+ web 0.5.1
Changed 16 dependencies!
6 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.

پیکربندی platform iOS

برای دریافت آخرین نسخه Google Maps SDK در iOS ، حداقل نسخه پلتفرم مورد نیاز iOS 14 است . قسمت بالای فایل پیکربندی ios/Podfile را به صورت زیر تغییر دهید.

ios/پادفایل

# Google Maps SDK requires platform version 14
# https://developers.google.com/maps/flutter-package/config#ios
platform :ios, '14.0'


# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

پیکربندی minSDK اندروید

برای استفاده از SDK نقشه‌های گوگل در اندروید، باید minSdk را روی ۲۱ تنظیم کنید . فایل پیکربندی android/app/build.gradle را به صورت زیر تغییر دهید.

اندروید/اپلیکیشن/ساخت.گرادل

android {
    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId = "com.example.google_maps_in_flutter"
        // Minimum Android version for Google Maps SDK
        // https://developers.google.com/maps/flutter-package/config#android
        minSdk = 21
        targetSdk = flutter.targetSdkVersion
        versionCode = flutterVersionCode.toInteger()
        versionName = flutterVersionName
    }

}

۴. افزودن نقشه‌های گوگل به برنامه

همه چیز در مورد کلیدهای API است

برای استفاده از نقشه‌های گوگل در برنامه Flutter خود، باید یک پروژه API را با پلتفرم نقشه‌های گوگل پیکربندی کنید، و از کلید Using API مربوط به Maps SDK برای اندروید ، کلید Using API مربوط به Maps SDK برای iOS و کلید Using API مربوط به Maps JavaScript API پیروی کنید . با در دست داشتن کلیدهای API، مراحل زیر را برای پیکربندی برنامه‌های اندروید و iOS انجام دهید.

افزودن کلید API برای برنامه اندروید

برای افزودن کلید API به برنامه اندروید، فایل AndroidManifest.xml را در android/app/src/main ویرایش کنید. یک ورودی meta-data واحد حاوی کلید API ایجاد شده در مرحله قبل را درون گره application اضافه کنید.

اندروید/برنامه/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:label="google_maps_in_flutter"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">

        <!-- TODO: Add your Google Maps API key here -->
        <meta-data android:name="com.google.android.geo.API_KEY"
               android:value="YOUR-KEY-HERE"/>

        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:taskAffinity=""
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
    <!-- Required to query activities that can process text, see:
         https://developer.android.com/training/package-visibility and
         https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.

         In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
    <queries>
        <intent>
            <action android:name="android.intent.action.PROCESS_TEXT"/>
            <data android:mimeType="text/plain"/>
        </intent>
    </queries>
</manifest>

افزودن کلید API برای یک برنامه iOS

برای افزودن کلید API به برنامه iOS، فایل AppDelegate.swift را در ios/Runner ویرایش کنید. برخلاف اندروید، افزودن کلید API در iOS نیاز به تغییراتی در کد منبع برنامه Runner دارد. AppDelegate هسته اصلی است که بخشی از فرآیند مقداردهی اولیه برنامه است.

دو تغییر در این فایل ایجاد کنید. ابتدا، یک عبارت #import برای دریافت هدرهای نقشه‌های گوگل اضافه کنید و سپس متد provideAPIKey() از سینگلتون GMSServices را فراخوانی کنید. این کلید API به نقشه‌های گوگل این امکان را می‌دهد که به درستی کاشی‌های نقشه را ارائه دهند.

ios/Runner/AppDelegate.swift

import Flutter
import UIKit
import GoogleMaps                                          // Add this import

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)

    // TODO: Add your Google Maps API key
    GMSServices.provideAPIKey("YOUR-API-KEY")               // Add this line

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

افزودن کلید API برای یک برنامه وب

برای افزودن کلید API به برنامه وب، فایل index.html را در web ویرایش کنید. در بخش head، یک ارجاع به اسکریپت جاوا اسکریپت Maps با کلید API خود اضافه کنید.

وب/ایندکس.html

<!DOCTYPE html>
<html>
<head>
  <!--
    If you are serving your web app in a path other than the root, change the
    href value below to reflect the base path you are serving from.

    The path provided below has to start and end with a slash "/" in order for
    it to work correctly.

    For more details:
    * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base

    This is a placeholder for base href that will be replaced by the value of
    the `--base-href` argument provided to `flutter build`.
  -->
  <base href="$FLUTTER_BASE_HREF">

  <meta charset="UTF-8">
  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
  <meta name="description" content="A new Flutter project.">

  <!-- iOS meta tags & icons -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="apple-mobile-web-app-title" content="google_maps_in_flutter">
  <link rel="apple-touch-icon" href="icons/Icon-192.png">

  <!-- Favicon -->
  <link rel="icon" type="image/png" href="favicon.png"/>

  <!-- Add your Google Maps API key here -->
  <script src="https://maps.googleapis.com/maps/api/js?key=YOUR-KEY-HERE"></script>

  <title>google_maps_in_flutter</title>
  <link rel="manifest" href="manifest.json">
</head>
<body>
  <script src="flutter_bootstrap.js" async></script>
</body>
</html>

قرار دادن نقشه روی صفحه نمایش

حالا وقتشه که یه نقشه روی صفحه نمایش بدیم. محتویات lib/main.dart رو ​​با کد زیر جایگزین کنید.

lib/main.dart

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

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late GoogleMapController mapController;

  final LatLng _center = const LatLng(45.521563, -122.677433);

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: Colors.green[700],
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Maps Sample App'),
          elevation: 2,
        ),
        body: GoogleMap(
          onMapCreated: _onMapCreated,
          initialCameraPosition: CameraPosition(
            target: _center,
            zoom: 11.0,
          ),
        ),
      ),
    );
  }
}

اجرای برنامه

برنامه Flutter را در iOS یا اندروید اجرا کنید تا یک نمای نقشه واحد، با محوریت پورتلند، مشاهده کنید. به عنوان یک راه حل جایگزین، می‌توانید از یک شبیه‌ساز اندروید یا یک شبیه‌ساز iOS استفاده کنید. می‌توانید مرکز نقشه را طوری تغییر دهید که نمایانگر شهر محل سکونت شما یا مکانی باشد که برایتان مهم است.

$ flutter run

اسکرین شاتی از یک برنامه Flutter با نقشه گوگل که در یک شبیه ساز آیفون اجرا می‌شود

اسکرین‌شاتی از یک برنامه Flutter با نقشه گوگل که در یک شبیه‌ساز اندروید اجرا می‌شود

۵. گوگل را روی نقشه قرار دهید

گوگل دفاتر زیادی در سراسر جهان دارد، از آمریکای شمالی ، آمریکای لاتین ، اروپا ، آسیا و اقیانوسیه گرفته تا آفریقا و خاورمیانه . نکته جالب در مورد این نقشه‌ها، اگر آنها را بررسی کنید، این است که یک نقطه پایانی API با قابلیت استفاده آسان برای ارائه اطلاعات مکان دفتر در قالب JSON دارند. در این مرحله، این مکان‌های دفتر را روی نقشه قرار می‌دهید. در این مرحله، از تولید کد برای تجزیه JSON استفاده خواهید کرد.

سه وابستگی جدید Flutter را به شرح زیر به پروژه اضافه کنید. بسته http را برای ایجاد آسان درخواست‌های HTTP، json_serializable و json_annotation برای تعریف ساختار شیء جهت نمایش اسناد JSON، و build_runner برای پشتیبانی از تولید کد اضافه کنید.

$ flutter pub add http json_annotation json_serializable dev:build_runner
Resolving dependencies... 
Downloading packages... 
+ _fe_analyzer_shared 67.0.0 (68.0.0 available)
+ analyzer 6.4.1 (6.5.0 available)
+ args 2.5.0
+ build 2.4.1
+ build_config 1.1.1
+ build_daemon 4.0.1
+ build_resolvers 2.4.2
+ build_runner 2.4.9
+ build_runner_core 7.3.0
+ built_collection 5.1.1
+ built_value 8.9.2
+ checked_yaml 2.0.3
+ code_builder 4.10.0
+ convert 3.1.1
+ crypto 3.0.3
+ dart_style 2.3.6
+ file 7.0.0
+ fixnum 1.1.0
+ frontend_server_client 4.0.0
+ glob 2.1.2
+ graphs 2.3.1
+ http 1.2.1
+ http_multi_server 3.2.1
+ http_parser 4.0.2
+ io 1.0.4
  js 0.6.7 (0.7.1 available)
+ json_annotation 4.9.0
+ json_serializable 6.8.0
  leak_tracker 10.0.4 (10.0.5 available)
  leak_tracker_flutter_testing 3.0.3 (3.0.5 available)
+ logging 1.2.0
  material_color_utilities 0.8.0 (0.11.1 available)
  meta 1.12.0 (1.14.0 available)
+ mime 1.0.5
+ package_config 2.1.0
+ pool 1.5.1
+ pub_semver 2.1.4
+ pubspec_parse 1.2.3
+ shelf 1.4.1
+ shelf_web_socket 1.0.4
+ source_gen 1.5.0
+ source_helper 1.3.4
  test_api 0.7.0 (0.7.1 available)
+ timing 1.0.1
+ typed_data 1.3.2
+ watcher 1.1.0
+ web_socket_channel 2.4.5
+ yaml 3.1.2
Changed 42 dependencies!
8 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.

تجزیه JSON با تولید کد

شاید متوجه شده باشید که داده‌های JSON که از API endpoint برگردانده می‌شوند، ساختار منظمی دارند. تولید کدی که این داده‌ها را در اشیاء قابل استفاده در کد مرتب کند، مفید خواهد بود.

در دایرکتوری lib/src ، یک فایل locations.dart ایجاد کنید و ساختار داده‌های JSON برگشتی را به صورت زیر توصیف کنید:

lib/src/locations.dart

import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:http/http.dart' as http;
import 'package:json_annotation/json_annotation.dart';

part 'locations.g.dart';

@JsonSerializable()
class LatLng {
  LatLng({
    required this.lat,
    required this.lng,
  });

  factory LatLng.fromJson(Map<String, dynamic> json) => _$LatLngFromJson(json);
  Map<String, dynamic> toJson() => _$LatLngToJson(this);

  final double lat;
  final double lng;
}

@JsonSerializable()
class Region {
  Region({
    required this.coords,
    required this.id,
    required this.name,
    required this.zoom,
  });

  factory Region.fromJson(Map<String, dynamic> json) => _$RegionFromJson(json);
  Map<String, dynamic> toJson() => _$RegionToJson(this);

  final LatLng coords;
  final String id;
  final String name;
  final double zoom;
}

@JsonSerializable()
class Office {
  Office({
    required this.address,
    required this.id,
    required this.image,
    required this.lat,
    required this.lng,
    required this.name,
    required this.phone,
    required this.region,
  });

  factory Office.fromJson(Map<String, dynamic> json) => _$OfficeFromJson(json);
  Map<String, dynamic> toJson() => _$OfficeToJson(this);

  final String address;
  final String id;
  final String image;
  final double lat;
  final double lng;
  final String name;
  final String phone;
  final String region;
}

@JsonSerializable()
class Locations {
  Locations({
    required this.offices,
    required this.regions,
  });

  factory Locations.fromJson(Map<String, dynamic> json) =>
      _$LocationsFromJson(json);
  Map<String, dynamic> toJson() => _$LocationsToJson(this);

  final List<Office> offices;
  final List<Region> regions;
}

Future<Locations> getGoogleOffices() async {
  const googleLocationsURL = 'https://about.google/static/data/locations.json';

  // Retrieve the locations of Google offices
  try {
    final response = await http.get(Uri.parse(googleLocationsURL));
    if (response.statusCode == 200) {
      return Locations.fromJson(
          json.decode(response.body) as Map<String, dynamic>);
    }
  } catch (e) {
    if (kDebugMode) {
      print(e);
    }
  }

  // Fallback for when the above HTTP request fails.
  return Locations.fromJson(
    json.decode(
      await rootBundle.loadString('assets/locations.json'),
    ) as Map<String, dynamic>,
  );
}

پس از افزودن این کد، IDE شما (اگر از آن استفاده می‌کنید) باید چند خط موج قرمز نشان دهد، زیرا به یک فایل همزادِ ناموجود، locations.g.dart. این فایل تولید شده، ساختارهای JSON بدون نوع را به اشیاء نامگذاری شده تبدیل می‌کند. با اجرای build_runner به شرح زیر، آن را ایجاد کنید:

$ dart run build_runner build --delete-conflicting-outputs
[INFO] Generating build script...
[INFO] Generating build script completed, took 357ms

[INFO] Creating build script snapshot......
[INFO] Creating build script snapshot... completed, took 10.5s

[INFO] There was output on stdout while compiling the build script snapshot, run with `--verbose` to see it (you will need to run a `clean` first to re-snapshot).

[INFO] Initializing inputs
[INFO] Building new asset graph...
[INFO] Building new asset graph completed, took 646ms

[INFO] Checking for unexpected pre-existing outputs....
[INFO] Deleting 1 declared outputs which already existed on disk.
[INFO] Checking for unexpected pre-existing outputs. completed, took 3ms

[INFO] Running build...
[INFO] Generating SDK summary...
[INFO] 3.4s elapsed, 0/3 actions completed.
[INFO] Generating SDK summary completed, took 3.4s

[INFO] 4.7s elapsed, 2/3 actions completed.
[INFO] Running build completed, took 4.7s

[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 36ms

[INFO] Succeeded after 4.8s with 2 outputs (7 actions)

اکنون کد شما باید دوباره به طور تمیز تجزیه و تحلیل شود. در مرحله بعد، باید فایل جایگزین locations.json را که در تابع getGoogleOffices استفاده می‌شود، اضافه کنیم. یکی از دلایل اضافه کردن این جایگزین این است که داده‌های استاتیک بارگذاری شده در این تابع بدون هدرهای CORS ارائه می‌شوند و بنابراین در مرورگر وب بارگذاری نمی‌شوند. برنامه‌های اندروید و iOS Flutter به هدرهای CORS نیاز ندارند، اما دسترسی به داده‌های تلفن همراه در بهترین حالت می‌تواند مشکل‌ساز باشد.

در مرورگر خود به https://about.google/static/data/locations.json بروید و محتویات را در دایرکتوری asset ذخیره کنید. همچنین می‌توانید از خط فرمان به شرح زیر استفاده کنید.

$ mkdir assets
$ cd assets
$ curl -o locations.json https://about.google/static/data/locations.json
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 30348  100 30348    0     0  75492      0 --:--:-- --:--:-- --:--:-- 75492

حالا که فایل asset را دانلود کرده‌اید، آن را به بخش flutter فایل pubspec.yaml خود اضافه کنید.

pubspec.yaml

flutter:
  uses-material-design: true

  assets:
    - assets/locations.json

فایل main.dart را برای درخواست داده‌های نقشه تغییر دهید و سپس از اطلاعات برگشتی برای اضافه کردن دفاتر به نقشه استفاده کنید:

lib/main.dart

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'src/locations.dart' as locations;

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final Map<String, Marker> _markers = {};
  Future<void> _onMapCreated(GoogleMapController controller) async {
    final googleOffices = await locations.getGoogleOffices();
    setState(() {
      _markers.clear();
      for (final office in googleOffices.offices) {
        final marker = Marker(
          markerId: MarkerId(office.name),
          position: LatLng(office.lat, office.lng),
          infoWindow: InfoWindow(
            title: office.name,
            snippet: office.address,
          ),
        );
        _markers[office.name] = marker;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: Colors.green[700],
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Google Office Locations'),
          elevation: 2,
        ),
        body: GoogleMap(
          onMapCreated: _onMapCreated,
          initialCameraPosition: const CameraPosition(
            target: LatLng(0, 0),
            zoom: 2,
          ),
          markers: _markers.values.toSet(),
        ),
      ),
    );
  }
}

این کد چندین عملیات انجام می‌دهد:

  • در _onMapCreated ، از کد تجزیه JSON از مرحله قبل استفاده می‌کند و await می‌ماند تا بارگذاری شود. سپس از داده‌های برگشتی برای ایجاد Marker ها در داخل یک فراخوانی setState() استفاده می‌کند. هنگامی که برنامه نشانگرهای جدید را دریافت می‌کند، setState به Flutter دستور می‌دهد تا صفحه را دوباره رنگ‌آمیزی کند و باعث نمایش مکان‌های دفتر شود.
  • نشانگرها در Map که با ویجت GoogleMap مرتبط است ذخیره می‌شوند. این نشانگرها را به نقشه صحیح پیوند می‌دهد. البته می‌توانید چندین نقشه داشته باشید و نشانگرهای مختلفی را در هر کدام نمایش دهید.

اسکرین‌شاتی از یک برنامه Flutter با نقشه گوگل که در یک شبیه‌ساز آیفون با نمای کوهستانی هایلایت شده اجرا می‌شود

این تصویری از کاری است که انجام داده‌اید. در این مرحله می‌توان موارد جالب زیادی را اضافه کرد. برای مثال، می‌توانید یک نمای فهرست از دفاتر اضافه کنید که وقتی کاربر روی یک دفتر کلیک می‌کند، نقشه را حرکت داده و بزرگنمایی کند، اما همانطور که می‌گویند، این تمرین به خواننده واگذار شده است!

۶. مراحل بعدی

تبریک می‌گویم!

شما آزمایشگاه کد را تکمیل کرده‌اید و یک برنامه Flutter با نقشه گوگل ساخته‌اید! همچنین با یک سرویس وب JSON تعامل داشته‌اید.

سایر مراحل بعدی

این آزمایشگاه کد، تجربه‌ای برای تجسم تعدادی از نقاط روی نقشه ایجاد کرده است. تعدادی برنامه تلفن همراه وجود دارد که بر اساس این قابلیت، نیازهای مختلف کاربران را برآورده می‌کنند. منابع دیگری نیز وجود دارند که می‌توانند به شما در پیشبرد این امر کمک کنند: