androidfluttergoogle-maps

Adding multiple markers in flutter


Before anything I want to prefice this with me being a complete noob in flutter. My project is a charging station finder using google maps api, the map has 2 different kind of markers, 1 for the charging station, and the other for the moving car, previously I had the charging stations individualy mapped out in an array like manner and then called them in the scaffold

Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
        style: _themeformap,
        mapType: MapType.normal,
        initialCameraPosition: _kGooglePlex,
        onMapCreated: (GoogleMapController controller) {
          _controller.complete(controller);
        },

        markers: //{
          // Marker(
          //   markerId: const MarkerId(''),
          //   icon: iconStation,
          //   position: ev01,
          // ),
          // Marker(
          //   markerId: const MarkerId(''),
          //   icon: iconStation,
          //   position: ev02,
          // ),
          // Marker(
          //   markerId: const MarkerId(''),
          //   icon: iconStation,
          //   position: ev03,
          // ),
          // Marker(
          //   markerId: const MarkerId(''),
          //   icon: iconStation,
          //   position: ev04,
          // ),
          // Marker(
          //   markerId: const MarkerId(''),
          //   icon: iconStation,
          //   position: ev05,
          // ),
        //},

      )

originally they were not comments, but after following a tutorial to have the car marker move with the location change the marker I should add next to these is

markers: //{
  usersCarArr.values.toSet(),

with the function for it being something like this

  void updateOtherCarLocation(Map obj) {
    usersCarArr[obj["uuid"].toString()] = Marker(
      markerId: MarkerId(obj["uuid"].toString()),
      position: LatLng(
        double.tryParse(obj["lat"].toString()) ?? 0.0,
        double.tryParse(obj["long"].toString()) ?? 0.0,
      ),
      icon: iconCar,
      rotation: double.tryParse(obj["degree"].toString()) ?? 0.0,
      anchor: const Offset(0.5, 0.5),
    );

    if (mounted) {
      setState(() {});
    }
  }

  void apiCarJoin() {
    ServiceCall.post(
      {
        "uuid": ServiceCall.userUUID,
        "lat": currentPosition.latitude.toString(),
        "long": currentPosition.longitude.toString(),
        "degree": LocationManager.shared.carDegree.toString(),
        "socket_id": SocketManager.shared.socket?.id ?? "",
      },
      SVKey.svCarJoin,
      (responseObj) async {
        if (responseObj[KKey.status] == "1") {
          (responseObj[KKey.payload] as Map? ?? {}).forEach((key, value) {
            usersCarArr[key.toString()] = Marker(
              markerId: MarkerId(key.toString()),
              position: LatLng(
                double.tryParse(value["lat"].toString()) ?? 0.0,
                double.tryParse(value["long"].toString()) ?? 0.0,
              ),
              icon: iconCar,
              rotation: double.tryParse(value["degree"].toString()) ?? 0.0,
              anchor: const Offset(0.5, 0.5),
            );
          });

          if (mounted) {
            setState(() {});
          }
        } else {
          debugPrint(responseObj[KKey.message] as String? ?? MSG.fail);
        }
      },
      (error) async {
        debugPrint(error.toString());
      },
    );
  }

and no matter what I can't for the life of me be able to have both of them co-exist it has to be one or the other, but I absolutely must have them both appear on the screen together


Solution

  • You need to combine all the markers into a single Set<Marker> and pass it to the GoogleMap widget
    Create a Set<Marker> , Set.addAll() to merge and Pass to the GoogleMap widget.

    import 'package:flutter/material.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    
    class MapScreen extends StatefulWidget {
      @override
      _MapScreenState createState() => _MapScreenState();
    }
    
    class _MapScreenState extends State<MapScreen> {
      final Set<Marker> _chargingStationMarkers = {
        Marker(
          markerId: MarkerId('ev01'),
          icon: iconStation,
          position: ev01,
        ),
        Marker(
          markerId: MarkerId('ev02'),
          icon: iconStation,
          position: ev02,
        ),
        Marker(
          markerId: MarkerId('ev03'),
          icon: iconStation,
          position: ev03,
        ),
        Marker(
          markerId: MarkerId('ev04'),
          icon: iconStation,
          position: ev04,
        ),
        Marker(
          markerId: MarkerId('ev05'),
          icon: iconStation,
          position: ev05,
        ),
      };
    
      final Map<String, Marker> _usersCarMarkers = {};
    
      @override
      Widget build(BuildContext context) {
        // Combine both sets of markers
        final Set<Marker> allMarkers = {..._chargingStationMarkers, ..._usersCarMarkers.values};
    
        return Scaffold(
          body: GoogleMap(
            mapType: MapType.normal,
            initialCameraPosition: _kGooglePlex,
            onMapCreated: (GoogleMapController controller) {
              _controller.complete(controller);
            },
            markers: allMarkers, // Pass the combined markers here
          ),
        );
      }
    
      void updateOtherCarLocation(Map obj) {
        _usersCarMarkers[obj["uuid"].toString()] = Marker(
          markerId: MarkerId(obj["uuid"].toString()),
          position: LatLng(
            double.tryParse(obj["lat"].toString()) ?? 0.0,
            double.tryParse(obj["long"].toString()) ?? 0.0,
          ),
          icon: iconCar,
          rotation: double.tryParse(obj["degree"].toString()) ?? 0.0,
          anchor: const Offset(0.5, 0.5),
        );
    
        if (mounted) {
          setState(() {});
        }
      }
    
      void apiCarJoin() {
        ServiceCall.post(
          {
            "uuid": ServiceCall.userUUID,
            "lat": currentPosition.latitude.toString(),
            "long": currentPosition.longitude.toString(),
            "degree": LocationManager.shared.carDegree.toString(),
            "socket_id": SocketManager.shared.socket?.id ?? "",
          },
          SVKey.svCarJoin,
          (responseObj) async {
            if (responseObj[KKey.status] == "1") {
              (responseObj[KKey.payload] as Map? ?? {}).forEach((key, value) {
                _usersCarMarkers[key.toString()] = Marker(
                  markerId: MarkerId(key.toString()),
                  position: LatLng(
                    double.tryParse(value["lat"].toString()) ?? 0.0,
                    double.tryParse(value["long"].toString()) ?? 0.0,
                  ),
                  icon: iconCar,
                  rotation: double.tryParse(value["degree"].toString()) ?? 0.0,
                  anchor: const Offset(0.5, 0.5),
                );
              });
    
              if (mounted) {
                setState(() {});
              }
            } else {
              debugPrint(responseObj[KKey.message] as String? ?? MSG.fail);
            }
          },
          (error) async {
            debugPrint(error.toString());
          },
        );
      }
    }