شرح الحصول على lat و lng للموقع في flutter (الحصول على احدثيات الموقع على الخريطة بالاسم)

شرح الحصول على lat و lng للموقع في flutter (الحصول على احدثيات الموقع على الخريطة بالاسم)

شرح الحصول على lat و lng للموقع في flutter (الحصول على احدثيات الموقع على الخريطة بالاسم)

في الدروس السابقة من شرح ال map في Flutter تعلمنا كيف نقوم بتركيب الخريطة في تطبيقك وايضا تعلمنا كيف نقوم بالبحث عن اي مكان في الخريطة ونظهر تفاصيل الموقع وفي هذا المكان سوف نقوم بعرض جميع تفاصيل الموقع والحصول على خط الطول والعرض الخاصين بالموقع وهما lat , lng لكي نستطيع الانتقال للموقع بمجرد النقر عليه ولهذا سوف نحتاج الى استخدام api مختلف نقوم بإرسال له ال id الخاص بالموقع وسوف يرجع لك تفاصيل الموقع بشكل كامل , وال id نستطيع الحصول عليه من خلال المقالة السابقه .


تنتج مجموعة أدوات تطوير Flutter تطبيقات الهاتف المحمول ثنائية الأبعاد مع جميع الأجراس والصفارات وجماليات العلامات التجارية الممتازة. Alibaba وتطبيق AdWords هما مثالان فقط لتطبيقات الجوال التي تعمل بنظام Flutter. الآن إطار عمل معروف ، Flutter لتطوير تطبيقات الهاتف المحمول لديه القوة لإنشاء العديد من تطبيقات الويب بنجاح وبتكلفة معقولة والتي تستجيب بشكل أسرع عبر جميع أحجام الشاشات. يرمز Flutter ، إطار عمل Google ، إلى "جعل تطوير التطبيقات أمرًا بسيطًا!" إذا كنت مهتمًا بدمج هذه المزايا في تطبيق الهاتف المحمول الخاص بك ، فيمكنك الاستفاده من موقعنا في انجاز اعمالك بشكل اسرع ودائما تذكر ان لا شيء في العالم الذي نعيش فيه اصبح صعب


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


برمجة جوجل:

تقدم جوجل مجموعة واسعة من الأدوات والتقنيات التي تساعد المطورين على إنشاء تطبيقات ذكية، بما في ذلك خرائط جوجل. يمكن استخدام خرائط جوجل لإنشاء تطبيقات متنوعة، مثل تطبيقات التنقل والتوصيل وتطبيقات العلامات التجارية والإعلانات.


برمجة تطبيقات الأجهزة الذكية:

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


إنشاء تطبيقات الاندرويد:

يمكن استخدام فلاتر لإنشاء تطبيقات أندرويد وiOS. فلاتر هي تقنية تطوير تطبيقات ذكية مفتوحة المصدر من جوجل، تعتمد على لغة البرمجة دارت.


برمجة تطبيقات الاجهزة الذكية:

تتضمن برمجة تطبيقات الأجهزة الذكية مجموعة من الخطوات، مثل:


  • تصميم التطبيق: يتضمن هذه الخطوة تحديد وظائف التطبيق وتصميم واجهة المستخدم.
  • تطوير التطبيق: يتضمن هذه الخطوة كتابة الكود وتنفيذه.
  • اختبار التطبيق: يتضمن هذه الخطوة اختبار التطبيق للتأكد من سلامة عمله.
  • نشر التطبيق: يتضمن هذه الخطوة نشر التطبيق على متجر التطبيقات.


برمجة تطبيق اندرويد بسيط:

يمكن إنشاء تطبيق اندرويد بسيط باستخدام فلاتر من خلال الخطوات التالية:

  1. إنشاء مشروع جديد باستخدام فلاتر.
  2. إضافة مكتبة خرائط جوجل إلى المشروع.
  3. إنشاء الخريطة وإضافة المواقع إليها.
  4. تشغيل التطبيق على جهاز أندرويد.


يعد التعامل مع خرائط جوجل باستخدام فلاتر طريقة رائعة لإنشاء تطبيقات ذكية تفاعلية. فلاتر هي تقنية قوية وسهلة الاستخدام، يمكن استخدامها لإنشاء تطبيقات متنوعة للأجهزة الذكية.


الميزات والأدوات المتوفرة في خرائط جوجل:

  • التنقل
  • البحث
  • عرض التضاريس
  • عرض الصور
  • عرض الاتجاهات
  • عرض المسافات
  • عرض الوقت المقدر للوصول
  • خطوات استخدام خرائط جوجل في فلاتر:


أمثلة لتطبيقات اندرويد التي تستخدم خرائط جوجل:

  • تطبيقات التنقل
  • تطبيقات التوصيل
  • تطبيقات العلامات التجارية والإعلانات
  • تطبيقات السياحة والسفر
  • تطبيقات التعليم
  • تطبيقات الألعاب


نصائح لبرمجة تطبيقات اندرويد باستخدام فلاتر:

  • استخدام مكتبة خرائط جوجل الرسمية.
  • اختيار لغة البرمجة المناسبة للمشروع.
  • تصميم واجهة مستخدم جذابة وسهلة الاستخدام.
  • اختبار التطبيق بعناية قبل نشره.


android sdk manager تحميل flutter developers applications create app android android studio mac


كيفية الحصول على نقاط الطول والعرض لموقع المستخدم على الخريطة في flutter

في البداية تحتاج الى اضافة الاكواد التاليه في الاماكن المخصصه لها كما هو موضح , في الدروس السابقة قمنا بإنشاء جميع هذه الclasses حيث اننا نقوم بتحويل ال json ونقوم بالحصول على البيانات من خلال ال api ونقوم بعرض البيانات داخل json والامور جميعها تطرقنا لها في الدروس السابقة ولا يوجد اختلاف كبير بينهم .


كيفية الحصول على نقاط الطول والعرض لموقع المستخدم على الخريطة في flutter

codes.dart


// --------------------------- Json File

class Place {
  late Result result;

  Place.fromJson(dynamic json) {
    result = Result.fromJson(json['result']);
  }
}

class Result {
  late Geometry geometry;

  Result.fromJson(dynamic json) {
    geometry = Geometry.fromJson(json['geometry']);
  }
}

class Geometry {
  late Location location;

  Geometry.fromJson(dynamic json) {
    location = Location.fromJson(json['location']);
  }
}

class Location {
  late double lat;
  late double lng;

  Location.fromJson(dynamic json) {
    lat = json['lat'];
    lng = json['lng'];
  }
}

// --------------------------- PlacesWebservices

const placeLocationBaseUrl = 'https://maps.googleapis.com/maps/api/place/details/json';

  Future<dynamic> getPlaceLocation(String placeId, String sessionToken) async {
    try {
      Response response = await dio.get(
        placeLocationBaseUrl,
        queryParameters: {
          'place_id': placeId,
          'fields': 'geometry',
          'key': googleAPIKey,
          'sessiontoken': sessionToken
        },
      );
      return response.data;
    } catch (error) {
      return Future.error("Place location error : ",
          StackTrace.fromString(('this is its trace')));
    }
  }

// --------------------------- MapsRepository

  Future<Place> getPlaceLocation(String placeId, String sessionToken) async {
    final place =
    await placesWebservices.getPlaceLocation(placeId, sessionToken);
    return Place.fromJson(place);
  }

// --------------------------- MapsCubit

  void emitPlaceLocation(String placeId, String sessionToken) {
    mapsRepository.getPlaceLocation(placeId, sessionToken).then((place) {
      emit(PlaceLocationLoaded(place));
    });
  }
  

تصميم لعرض الخريطة مع اظهار الموقع بعد الانتقال اليه على الخريطة

بعد كتابة الاكواد التاليه ووضعها في الاماكن الصحيحه ناتي لتفعيل الخاصية داخل ui ولهذا نحتاج استخدام بعض الوظائف التي تعمل على تنفيذ المطلوب يمكنك نسخ الكود التالي والتعامل معه في تطبيقك وكل سطر تم كتابته قمنا بشرح الوظيفة التي يقوم بها حتى نسهل الموضوع عليكم في التعامل مع Maps وكما نعلم انها عنصر مهم من تطوير تطبيقات الجوال وكثير من العملاء يطلون الخريطة في تطبيقاتهم .


تصميم لعرض الخريطة مع اظهار الموقع بعد الانتقال اليه على الخريطة

ui.dart


class MainMaps extends StatefulWidget {
  const MainMaps({Key? key}) : super(key: key);

  @override
  State<MainMaps> createState() => _MainMapsState();
}

class _MainMapsState extends State<MainMaps> {
  // التعرف على موقع المستخدم
  static Position? position;
  // الانتقال المباشر الى موقع المستخدم بمجرد فتح التطبيق
  final Completer<GoogleMapController> _controllerMaps = Completer();
  // المتحكم في عمليات البحث داخل التطبيق
  FloatingSearchBarController controller = FloatingSearchBarController();
  // اضافة علامه على الخريطة للموقع الذي تم البحث والانتقال اليه
  late Marker searchedPlaceMarker;
  // اضافة علامه على الخريطة لموقعك
  late Marker currentLocationMarker;
  // العناصر التي تظهر بعد البحث عليها
  List<PlaceSuggestion> places = [];
  // اضافة علامه على الخريطة ومن نوع set لكي لا تتكرر
  Set<Marker> markers = {};
  // قيمة المكان الذي تم النقر عليه
  late Place selectedPlace;
  // تحريك الكاميرا الى الموقع الذي تم النقر عليه بعد البحث
  late CameraPosition goToSearchedForPlace;
  // معلوماات عن الموقع الذي تم البحث عنه
  late PlaceSuggestion placeSuggestion;

  // موقع المستخدم الحالي على الخريطة
  static final CameraPosition _myCurrentLocationNow = CameraPosition(
    //عرض موقع المستخدم على الخريطة مع بعض الخصائص مثل نسبة التقريب
    // نسبة جعل الكاميرا مائله
    bearing: 0.0,
    // موقع المستخدم
    target: LatLng(position!.latitude, position!.longitude),
    tilt: 0.0,
    // نسبة التقريب
    zoom: 18,
  );

  // تحريك الكاميرا الى موقع المستخدم
  Future<void> getMyLocationNow() async {
    // الحصول على موقع المستخدم بمجرد فتح الخريطة وتحديث الصفحة بالموقع الحالي
    position = await LocationHelper.getCurrentLocation().whenComplete(() => setState((){}));
  }

  // تحريك الكاميرا الى الموقع الذي تم الحصول على متغيراته
  Future<void> _goToMyLocationNow() async {
  // الانتقال الى موقعي بمجرد تنفيذ هذه الوظيفة
  final GoogleMapController controller = await _controllerMaps.future;
  // الانتقال الى موقع المستخدم الموجود في CameraPosition مع انميشن بسيط لحركة الكاميرا
  controller.animateCamera(CameraUpdate.newCameraPosition(_myCurrentLocationNow));
  }

  // الانتقال الى الموقع الذي تم البحث عنده بعد النقر عليه
  void buildCameraNewPosition() {
    goToSearchedForPlace = CameraPosition(
      bearing: 0.0,
      tilt: 0.0,
      target: LatLng(
        selectedPlace.result.geometry.location.lat,
        selectedPlace.result.geometry.location.lng,
      ),
      zoom: 13,
    );
  }

  //  الانتقال الى الموقع الذي تم البحث عنه و اضافة علامه على الخريطو
  Future<void> goToMySearchedForLocation() async {
    // بناء كاميرا جديده للتحريك
    buildCameraNewPosition();
    // تحريك الكاميرا
    final GoogleMapController controller = await _controllerMaps.future;
    controller
        .animateCamera(CameraUpdate.newCameraPosition(goToSearchedForPlace));
    // اضافة علامه على الخريطة
    buildSearchedPlaceMarker();
  }

  // اضافة علامه على الخريطة لموقع المستخدم
  void buildCurrentLocationMarker() {
    currentLocationMarker = Marker(
      position: LatLng(position!.latitude, position!.longitude),
      markerId: MarkerId('2'),
      onTap: () {},
      infoWindow: InfoWindow(title: "Your current Location"),
      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
    );
    addMarkerToMarkersAndUpdateUI(currentLocationMarker);
  }

  // اضافة علامه على الخريطة للموقع الذي تم البحث عنه
  void buildSearchedPlaceMarker() {
    searchedPlaceMarker = Marker(
      position: goToSearchedForPlace.target,
      markerId: MarkerId('1'),
      onTap: () {
        buildCurrentLocationMarker();
      },
      infoWindow: InfoWindow(title: "${placeSuggestion.description}"),
      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
    );

    addMarkerToMarkersAndUpdateUI(searchedPlaceMarker);
  }

  // اضافة علامة داخل ال list of Marker على الخريطة
  void addMarkerToMarkersAndUpdateUI(Marker marker) {
    setState(() {
      markers.add(marker);
    });
  }

  // البحث عن مجموعه من المدن في الخريطة في شريط البحث
  void getPlacesSuggestions(String query) {
    final sessionToken = Uuid().v4();
    BlocProvider.of<MapsCubit>(context)
        .emitPlaceSuggestions(query, sessionToken);
  }

  // ازالة جميع العلامات على الخريطة
  void removeAllMarkersAndUpdateUI() {
    setState(() {
      markers.clear();
    });
  }

  // عرض تفاصيل الموقع الذي تم النقر عليه بعد البحث
  void getSelectedPlaceLocation() {
    final sessionToken = Uuid().v4();
    BlocProvider.of<MapsCubit>(context)
        .emitPlaceLocation(placeSuggestion.placeId, sessionToken);
  }

  @override
  void initState() {
    super.initState();
    // عرض بيانات الموقع الحالي للمستخدم عند تشغيل التطبيق
    getMyLocationNow();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        fit: StackFit.expand,
        children: [
          position == null ? const Center(child: CircularProgressIndicator()) :
              // عرض الخريطة
          buildMaps(),
          // اضافة شريط للبحث في الاعلى
          buildFloatingSearchBar(),
        ],
      ),
      // بناء شريط جانبي
      drawer: MyDrawer(),
      floatingActionButton: FloatingActionButton(
        onPressed: _goToMyLocationNow,
        child: const Icon(Icons.location_searching),
      ),
    );
  }

  // الخريطة
  Widget buildMaps(){
    return GoogleMap(
      // نوع الخريطة
      mapType: MapType.normal,
      // وجود علامة زرقاء لاظهار موقعك الحالي على الخريطة
      myLocationEnabled: true,
      // اضافة زر في اعلى الخريطة للانتقال المباشر الى موقعك الحالي
      myLocationButtonEnabled: false,
      // وجود علامة التكبير والتصغير للخريطة في اسفل الخريطة
      zoomControlsEnabled: false,
      // الحصول على موقع المستخدم بمجرد فتح الخريطة وتحديث الصفحة بالموقع الحالي
      initialCameraPosition: _myCurrentLocationNow,

      onMapCreated: (GoogleMapController controller){
        _controllerMaps.complete(controller);
      },

    );
  }

  // البحث
  Widget buildFloatingSearchBar() {
    final isPortrait =
        MediaQuery.of(context).orientation == Orientation.portrait;

    return FloatingSearchBar(
      controller: controller,
      elevation: 6,
      hintStyle: TextStyle(fontSize: 18),
      queryStyle: TextStyle(fontSize: 18),
      hint: 'Find a place..',
      border: BorderSide(style: BorderStyle.none),
      margins: EdgeInsets.fromLTRB(20, 70, 20, 0),
      padding: EdgeInsets.fromLTRB(2, 0, 2, 0),
      height: 52,
      iconColor: Colors.blue[200],
      scrollPadding: const EdgeInsets.only(top: 16, bottom: 56),
      transitionDuration: const Duration(milliseconds: 600),
      transitionCurve: Curves.easeInOut,
      physics: const BouncingScrollPhysics(),
      axisAlignment: isPortrait ? 0.0 : -1.0,
      openAxisAlignment: 0.0,
      width: isPortrait ? 600 : 500,
      debounceDelay: const Duration(milliseconds: 500),
      progress: progressIndicator,
      onQueryChanged: (query) {
        getPlacesSuggestions(query);
      },
      onFocusChanged: (_) {
        // hide distance and time row
        setState(() {
          isTimeAndDistanceVisible = false;
        });
      },
      transition: CircularFloatingSearchBarTransition(),
      actions: [
        FloatingSearchBarAction(
          showIfOpened: false,
          child: CircularButton(
              icon: Icon(Icons.place, color: Colors.black.withOpacity(0.6)),
              onPressed: () {}),
        ),
      ],
      builder: (context, transition) {
        return ClipRRect(
          borderRadius: BorderRadius.circular(8),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              buildSuggestionsBloc(),
              buildSelectedPlaceLocationBloc(),
              buildDirectionsBloc(),
            ],
          ),
        );
      },
    );
  }

  // عندما يتم النقر على العنصر بعد البحث
  Widget buildSelectedPlaceLocationBloc() {
    return BlocListener<MapsCubit, MapsState>(
      listener: (context, state) {
        if (state is PlaceLocationLoaded) {
          selectedPlace = (state).place;
          // يتم الانتقال اليه
          goToMySearchedForLocation();
        }
      },
      child: Container(),
    );
  }

  // عندما يتم النقر على عنصر بعد البحث
  Widget buildSuggestionsBloc() {
    return BlocBuilder<MapsCubit, MapsState>(
      builder: (context, state) {
        if (state is PlacesLoaded) {
          places = (state).places;
          if (places.length != 0) {
            return buildPlacesList();
          } else {
            return Container();
          }
        } else {
          return Container();
        }
      },
    );
  }

  // عرض قائمه بجميع العناصر التي تم البحث عنها
  Widget buildPlacesList() {
    return ListView.builder(
        itemBuilder: (ctx, index) {
          return InkWell(
            onTap: () async {
              placeSuggestion = places[index];
              controller.close();
              getSelectedPlaceLocation();
              removeAllMarkersAndUpdateUI();
            },
            child: PlaceItem(
              suggestion: places[index],
            ),
          );
        },
        itemCount: places.length,
        shrinkWrap: true,
        physics: const ClampingScrollPhysics());
  }

}


تعليقات