Sunshine
Sunshine

Reputation: 334

Stack CustomPaint widgets on GoogleMap Widget with right coordinates

EDIT : turns out my question was related to this open Github issue https://github.com/flutter/flutter/issues/41731

So for now I only need help figuring out how to display my markers not as BitmapDescriptor but just simply stacked on top of my Google maps widget as CustomPaint widgets

As described in GitHub this comment but I don't know how it would work for it to be responsive and markers to display at the right place on the map

It would look something like this :

    Stack(
      children: [
        MyMarkersDisplayingAtTheRightCoordinates(),
        GoogleMap(...)
      ],
    );

Upvotes: 1

Views: 508

Answers (1)

Karandeep Singh
Karandeep Singh

Reputation: 26

Showing markers on top of the Google map widget as a CustomPaint widget is very expensive because of two major reasons-

  1. Google maps UI is a platform native view. It does not provide the current selected visible screen LatLngBounds, Zoom level as a data stream. Which is required to calculate the marker position to make it responsive.

  2. It's gonna be development and computationally expensive to calculate the marker position based on the currently selected projection of google maps. And subsequently building the marker widgets based on google maps projection changes.

There are two ways to add markers to google maps,

  1. You can pass BitmapDiscriptor an image- BitmapDescriptor.fromAssetImage(ImageConfiguration.empty, 'map_marker.png');

This is an optimal and recommended way if you want to show multiple markers https://github.com/flutter/flutter/issues/41731#issuecomment-538370982.

  1. You can pass the Uint8List format of image data to BitmatpDiscriptor as well. If you want to show widgets as markers then you can calculate the Uint8List of flutter widget using screenshot package as well. Here is an example,
ScreenshotController screenshotController = ScreenshotController();  
late Future<Uint8List> marker;
  @override
  void initState() {
    super.initState();
    marker = screenshotController.captureFromWidget(SizedBox(
      width: 25,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Center(
            child: Container(
              decoration: const BoxDecoration(
                shape: BoxShape.circle,
                color: Colors.orange,
              ),
              height: 18,
              width: 18,
            ),
          ),
          Container(
            decoration: const BoxDecoration(
              shape: BoxShape.circle,
              color: Colors.red,
            ),
            height: 25,
            width: 25,
          ),
        ],
      ),
    ));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder(
          future: marker,
          builder: (context, snapshot) {
            final data = snapshot.data;
            if (data != null && data is Uint8List) {
              print('Length: ${data.length}');
              return GoogleMap(
                  mapType: MapType.hybrid,
                  initialCameraPosition: _kGooglePlex,
                  onMapCreated: (GoogleMapController controller) {
                    _controller.complete(controller);
                  },
                  markers: <Marker>{
                    Marker(
                        markerId: const MarkerId('custom_marker'),
                        position: const LatLng(37.42796133580664, -122.085749655962),
                        icon: BitmapDescriptor.fromBytes(data))
                  });
            } else {
              return const Text('Something went wrong');
            }
          }),
    );
  }
}

If you don't want to use screenshot package. Then you can create a const Uint8List variables for the custom_markers as well.

Upvotes: 1

Related Questions