الخرائط والموقع وميزات الجهاز

مقدمة إلى google_maps_flutter

15 دقيقة الدرس 1 من 12

مقدمة إلى google_maps_flutter

حزمة google_maps_flutter هي الإضافة الرسمية لـ Flutter لتضمين خرائط Google في تطبيقات Android وiOS. توفر هذه الحزمة ودجت GoogleMap يغلّف حزمة Google Maps SDK الأصيلة على كل منصة، مما يتيح لك الوصول الكامل إلى العلامات والخطوط متعددة الأضلاع والمضلعات وعناصر التحكم بالكاميرا وتبديل نوع الخريطة — وكل ذلك من خلال واجهة Flutter التصريحية.

في هذا الدرس ستضيف الحزمة إلى مشروع، وتهيئ مفاتيح API المطلوبة لكلتا المنصتين، وتعرض أول خريطة تفاعلية لك بموضع كاميرا ثابت.

ملاحظة: تتطلب حزمة google_maps_flutter مفتاح Google Maps API صالحاً مع تفعيل واجهتَي برمجة التطبيقات Maps SDK for Android وMaps SDK for iOS في Google Cloud Console. بدون مفتاح ستُعرض الخريطة كشبكة رمادية.

الخطوة 1 — إضافة الحزمة

افتح ملف pubspec.yaml الخاص بمشروعك وأضف الاعتمادية تحت قسم dependencies:

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  google_maps_flutter: ^2.9.0

بعد الحفظ، نفّذ الأمر flutter pub get لجلب الحزمة. تقوم الإضافة تلقائياً بربط حزمة Google Maps SDK الأصيلة على Android وiOS عبر نظام الإضافات في Flutter — لا حاجة لتعديلات Gradle أو CocoaPods يدوية للإضافة نفسها، فقط إعداد مفتاح API الموضح أدناه.

الخطوة 2 — إعداد مفتاح API لنظام Android

افتح ملف android/app/src/main/AndroidManifest.xml وأضف عنصر <meta-data> داخل وسم <application>:

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <application
      android:label="my_app"
      android:icon="@mipmap/ic_launcher">

    <!-- مفتاح Google Maps API -->
    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="YOUR_ANDROID_API_KEY"/>

    <activity ... />
  </application>
</manifest>
تحذير: لا تكتب مفتاح API للإنتاج مباشرةً في ملفات المصدر المراقبة بنظام التحكم في الإصدارات. استخدم ملف local.properties (المدرج مسبقاً في .gitignore) أو حقن البيئة عبر خط أنابيب CI/CD. العنصر النائب أعلاه مناسب للتطوير لكن يجب تأمينه قبل الشحن.

تأكد أيضاً من أن إصدار SDK الأدنى في android/app/build.gradle لا يقل عن 21:

android/app/build.gradle

android {
    defaultConfig {
        minSdkVersion 21   // google_maps_flutter يتطلب API 21+
        targetSdkVersion 34
    }
}

الخطوة 3 — إعداد مفتاح API لنظام iOS

افتح ملف ios/Runner/AppDelegate.swift واستدعِ الدالة GMSServices.provideAPIKey قبل تشغيل محرك Flutter:

ios/Runner/AppDelegate.swift

import UIKit
import Flutter
import GoogleMaps   // 1. استيراد SDK

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    // 2. تمرير مفتاح API قبل GeneratedPluginRegistrant
    GMSServices.provideAPIKey("YOUR_IOS_API_KEY")

    GeneratedPluginRegistrant.register(with: self)
    return super.application(application,
                             didFinishLaunchingWithOptions: launchOptions)
  }
}
نصيحة: إذا كان مشروعك يستخدم Objective-C بدلاً من Swift، استدعِ [GMSServices provideAPIKey:@"YOUR_IOS_API_KEY"] في ملف AppDelegate.m قبل [GeneratedPluginRegistrant registerWithRegistry:self].

ثم نفّذ الأمر cd ios && pod install (أو flutter pub get الذي يُشغّل pod install تلقائياً عند التشغيل الأول) لكي يربط CocoaPods إطار عمل GoogleMaps.

الخطوة 4 — عرض ودجت GoogleMap الأساسي

بعد إضافة الحزمة وإعداد المفاتيح، يمكنك الآن تضمين خريطة في أي مكان في شجرة الودجات. يتطلب ودجت GoogleMap معاملاً إلزامياً واحداً هو: initialCameraPosition. يحتاج CameraPosition على الأقل إلى هدف LatLng ومستوى تكبير.

ودجت GoogleMap الأساسي

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

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

  @override
  State<MapScreen> createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  // اختياري: الاحتفاظ بمرجع لتحريك الكاميرا لاحقاً
  GoogleMapController? _controller;

  static const CameraPosition _initialPosition = CameraPosition(
    target: LatLng(24.7136, 46.6753), // الرياض، المملكة العربية السعودية
    zoom: 12.0,
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('الخريطة')),
      body: GoogleMap(
        initialCameraPosition: _initialPosition,
        onMapCreated: (GoogleMapController controller) {
          _controller = controller;
        },
        myLocationButtonEnabled: false,
        zoomControlsEnabled: true,
      ),
    );
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }
}

النقاط الرئيسية من الكود أعلاه:

  • initialCameraPosition — إلزامي؛ يحدد الموضع الذي تتجه إليه الكاميرا عند تحميل الخريطة لأول مرة.
  • onMapCreated — دالة رد النداء التي تُطلق مرة واحدة بعد أن تصبح الخريطة الأصيلة جاهزة؛ استخدمها لتخزين GoogleMapController لتحريك الكاميرا لاحقاً.
  • GoogleMapController.dispose() — يجب استدعاؤها في dispose() لتحرير موارد الخريطة الأصيلة وتجنب تسرب الذاكرة.
  • myLocationButtonEnabled: false — يعطّل النقطة الزرقاء والزر حتى تطلب صلاحية location (ستتناولها درس لاحق).

مرجع مستويات التكبير

خاصية zoom في CameraPosition تتبع المقياس القياسي لخرائط Google:

  • 1 — عرض العالم
  • 5 — قارة / دولة كبيرة
  • 10 — مدينة
  • 15 — شوارع
  • 20 — مبانٍ / كتل فردية
نصيحة: يمكنك أيضاً تحديد bearing (الدوران بالدرجات، 0 = شمال) وtilt (0–90 درجة) في CameraPosition للحصول على عرض منظوري. في معظم حالات الاستخدام، القيم الافتراضية (bearing: 0، tilt: 0) كافية.

ملخص

في هذا الدرس تعلمت كيفية:

  • إضافة google_maps_flutter إلى pubspec.yaml وتشغيل flutter pub get.
  • تسجيل مفتاح Maps API في AndroidManifest.xml لنظام Android.
  • استدعاء GMSServices.provideAPIKey في AppDelegate.swift لنظام iOS.
  • عرض ودجت GoogleMap مع CameraPosition ثابت.
  • تخزين GoogleMapController والتخلص منه بشكل صحيح لتجنب تسرب الذاكرة.
الخطوة التالية: في الدروس التالية ستضيف علامات، وتتعامل مع نقرات المستخدم على الخريطة، وتحرّك الكاميرا برمجياً لبناء تجارب أكثر ثراءً تدرك الموقع الجغرافي.