Home > Mobile >  How to add markers to a flutter google map after the map has been created and change the camera posi
How to add markers to a flutter google map after the map has been created and change the camera posi

Time:12-16

I am new to Flutter and I have created a google map using the flutter_google_maps package.

I have the following code in my parent widget,

SizedBox(
    child: _showFindHouseModal
    ? FutureBuilder<Address?>(
        future: _locationDataFuture,
        builder: (context, snapshot) {

            if (snapshot.hasData) {
                return Map(
                    initialLatitude: _userLocation.latitude!.toDouble(),
                    initialLongitude: _userLocation.longitude!.toDouble(),
                    markers: const [],
                );
            }
        },
    )
    : FutureBuilder<Address?>(
        future: _showFindHouseModal,
        builder: (context, snapshot) {
            if (snapshot.hasData) {
                return Map(         // <---------------------------------------- This one is the problem
                    initialLongitude: _userLocation.latitude!.toDouble(),
                    initialLatitude: _userLocation.latitude!.toDouble(),
                    markers: [
                        Marker(
                            markerId: MarkerId('${_housesList.first.id}'),
                            position: LatLng(_housesList.first.houseLatitude, _housesList.first.houseLongitude),
                        ),
                    ],
                );
            }
        }),
),

In the above code, you can see that I am using a ternary operator. if _showFindHouseModal is true a Map widget is built. If it is not true, the same Map widget will be built but with additional markers. The problem is, those additional markers I am forwarding are not rendered on the screen.

However, I think I figured out the problem. It is in the child widget. (It is that I can not find a solution to the problem)

Let me show the code for the child widget.

class Map extends StatefulWidget {

  final List<Marker> markers;
  final double initialLatitude;
  final double initialLongitude;

  const Map({
    Key? key,
    required this.initialLatitude,
    required this.initialLongitude,
    required this.markers, // Todo: Make the default to an empty value
  }) : super(key: key);

  @override
  State<Map> createState() => MapState();
}

class MapState extends State<Map> {
  late final CameraPosition _initialCameraPosition;

  late final Set<Marker> _markers = {};

  final Completer<GoogleMapController> _controller = Completer();

  @override
  void initState() {
    super.initState();

    _initialCameraPosition = CameraPosition(
      target: LatLng(widget.initialLatitude, widget.initialLongitude),
      zoom: 12,
    );
  }

  @override
  Widget build(BuildContext context) {
    return GoogleMap(
      mapType: MapType.normal,
      initialCameraPosition: _initialCameraPosition,
      markers: _markers,
      onMapCreated: (GoogleMapController controller) {
        _controller.complete(controller);

        setState(
          () {
            _markers.addAll(widget.markers);  <--------- This is the problem I think
            _markers.add(
              Marker(
                markerId: const MarkerId('user-marker'),
                position: LatLng(widget.initialLatitude, widget.initialLongitude),
              ),
            );
          },
        );
      },
    );
  }
}

As I have pointed out in the code, I think the problem is, inside the child widget, those markers are added under the onMapCreated property. Since the map is already created in the first FutureBuilder, those markers are not added to the map for some reason. I can not figure out how to add new markers from the second FutureBuilder. The markers I am adding are not passed through.

Can someone please help. I have been trying to find a way for 6 or so hours and could not make it.

CodePudding user response:

try this, change the line you assign the markers

  markers: _markers

along this line

markers: Set<Marker>.of(_markers.values),

CodePudding user response:

this may help you

bool mapToggle = false;
  Position currentLocation;
  GoogleMapController mapController;
  GoogleMap googleMap;
  var ads = [];
  Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
  MarkerId selectedMarker;
  LatLng markerPosition;
  bool clientToggle = false;
  @override
  void initState() {
    super.initState();
    // GeolocationStatus geolocationStatus  = await Geolocator.checkGeolocationPermissionStatus();
    // Geolocator.checkPermission();
    // Geolocator.getServiceStatusStream();
    Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
        .then((currloc) {
      setState(() {
        currentLocation = currloc;
        mapToggle = true;
        populateClient();
      });
    });
  }



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

  populateClient() {
    kfirestore.collection('marks').get().then((value) {
      if (value.docs.isNotEmpty) {
        setState(() {
          clientToggle = true;
        });
        for (int i = 0; i < value.docs.length; i  ) {
          ads.add(value.docs[i].data());
          initMarker(value.docs[i].data(), value.docs[i].id);
          var _distanceBetweenLastTwoLocations = Geolocator.distanceBetween(
            value.docs[i].data()['location'].latitude,
            value.docs[i].data()['location'].longitude,
            currentLocation.latitude,
            currentLocation.longitude,
          );
          print("bairshiluud:"   _distanceBetweenLastTwoLocations.toString());
          if (_distanceBetweenLastTwoLocations < 100) {
            SuccessDialog(
              title: "Таны байршилтай ойр сурталчилгаа",
              titleColor: Colors.green,
              description: value.docs[i].data()['adName'],
            );
          } else {
            SuccessDialog(
              title: "Таны байршилтай ойр сурталчилгаа",
              titleColor: Colors.green,
              description: "Таны байршилд ойр сурталчилгаа олдсонгүй.",
            );
          }
        }
      }
    });
  }

  void initMarker(specify, specifyId) async {
    var markerIdVal = specifyId;
    final MarkerId markerId = MarkerId(markerIdVal);
    final Marker marker = Marker(
      markerId: markerId,
      position: LatLng(
        specify['location'].latitude,
        specify['location'].longitude,
      ),
      infoWindow: InfoWindow(title: specify['adName'], snippet: "Сурталчилгаа"),
      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRose),
    );
    setState(() {
      markers[markerId] = marker;
    });
  }

Container(
                  height: MediaQuery.of(context).size.height - 80,
                  width: double.infinity,
                  child: mapToggle
                      ? GoogleMap(
                          mapType: MapType.hybrid,
                          compassEnabled: true,
                          onMapCreated: onMapCreated,
                          buildingsEnabled: true,
                          myLocationButtonEnabled: true,
                          myLocationEnabled: true,
                          rotateGesturesEnabled: true,
                          zoomControlsEnabled: true,
                          zoomGesturesEnabled: true,
                          indoorViewEnabled: true,
                          mapToolbarEnabled: true,
                          tiltGesturesEnabled: true,
                          scrollGesturesEnabled: true,
                          initialCameraPosition: CameraPosition(
                            target: LatLng(currentLocation.latitude,
                                currentLocation.longitude),
                            zoom: 15,
                          ),
                          // circles: circles,
                          markers: Set<Marker>.of(markers.values),
                        )
                      : Center(
                          child: Text("Loading"),
                        ),
                ),

CodePudding user response:

1- It is not high possibile but maybe you can change markers: const [] line to just [] without cons keyword.

2- This one more possible than first one, try to cover with one of them future builder, with different widget like SizedBox or give one of them unique key. (but i suggest first approach like; condition? FutureBuilder:SizedBox(child: FutureBuilder)) because, your problem can be releated widget tree rendering. İf this solve your problem I can add a youtube link about that and you can understand the meaning what I am trying to point out.

3- for camera position, after on camera create function call, with help initialed googleMapsController, you can change camera position, camera zoom and some other stuffs with googleMapsController.animateCamera() function,

example; googleMapsController.animateCamera(CameraUpdate.newLatLng(latLng)) will change the google maps view to your new lat long point. So I suggest, dont't use future builder for this, just animate your camera after initialing and you can cover your map widget with IgnorePointer before getting locations, in this way you can ensure the animation can't block from user interaction.

  • Related