fluttermapboxmapbox-marker

Add draggable marker to flutter app mapbox


I am building a flutter app using the mapbox_maps_flutter: 0.4.4 package. There is no official flutter documentation so I am just using the examples and the android api to figure things out. But what i am trying to achieve is have a custom marker icon on my map that is initially in the same position as the user's current location, and then anytime I drag scroll on the map, the marker moves (by taking the center point of the camera). If this is too complex, then I would just like the marker to be draggable (like the uber app when you're requesting a trip).

I don't mind being pointed to some flutter documentation or at least a good and detailed example on how to use markers.

Lastly, please e aware that I am using version 0.44 which is no longer compatible with mapbox_gl I believe.

Here's some relevant code:

MapboxMap? mapboxMap;

_onMapCreated(MapboxMap mapboxMap) async {
    this.mapboxMap = mapboxMap;
    mapboxMap.location
        .updateSettings(LocationComponentSettings(enabled: true)); // show current position
    mapboxMap.scaleBar.updateSettings(ScaleBarSettings(
      enabled: false,)); // hide the scale bar
    mapboxMap.compass.updateSettings(CompassSettings(
      enabled: false,)); // hide the compass
  }

Widget _map() {
    return SizedBox(
      height: MediaQuery.of(context).size.height * 0.8, //mapbox needs to have a height
      child: MapWidget(
          resourceOptions: ResourceOptions(accessToken: MAPBOX_ACCESS_TOKEN),
        onMapCreated: _onMapCreated,
        key: const ValueKey("mapWidget"),
        cameraOptions: CameraOptions(
            center: Point(
                coordinates: Position(
                  widget.location.longitude,
                  widget.location.latitude,
                )).toJson(),
            zoom: 17.5
        ),
      )
    );
  }

Solution

  • I figured it out. As I said before, the mapbox_maps_flutter: 0.4.4 is AS OF THIS MOMENT not compatible with mapbox_gl. The way to add custom_markers is to use point annotations in conjunction with the annotation manager.

    Here's what the setup looks like:

        MapboxMap? mapboxMap;
        PointAnnotationManager? pointAnnotationManager;
        PointAnnotation? pointAnnotation;
        
        _onMapCreated(MapboxMap mapboxMap) async {
            this.mapboxMap = mapboxMap;
            mapboxMap.annotations.createPointAnnotationManager().then((value) async {
              pointAnnotationManager = value;
              _createMarker();
            });
          }
    
    Future<void> _createMarker({double currentLat = 0, double currentLong = 0, }) async {
        final ByteData bytes =
        await rootBundle.load('assets/images/marker.png');
        final Uint8List list = bytes.buffer.asUint8List();
    
        pointAnnotationManager
            ?.create(PointAnnotationOptions(
            geometry: Point(
                coordinates: Position(
                  currentLong == 0
                      ? widget.postLongitude != 0 ? widget.postLongitude : widget.location.longitude
                      : currentLong,
                  currentLat == 0
                      ? widget.postLatitude != 0 ? widget.postLatitude : widget.location.latitude
                      : currentLat,
                )).toJson(),
            iconSize: 2.5,
            iconOffset: [0.0, -10.0],
            symbolSortKey: 10,
            image: list))
            .then((value) => pointAnnotation = value);
      }
    

    The above is how to create the marker and place it at an arbitrary initial gps location. The below shows how to move the marker when you drag scroll on the map or when you click anywhere within the map:

    Widget _map() {
        return SizedBox(
          height: MediaQuery.of(context).size.height * 0.8, //mapbox needs to have a height
          child: MapWidget(
              resourceOptions: ResourceOptions(accessToken: MAPBOX_ACCESS_TOKEN),
            onMapCreated: _onMapCreated,
            key: const ValueKey("mapWidget"),
            onScrollListener: (screenCoordinate) {
              pointAnnotationManager?.deleteAll();
              _createMarker(currentLat: screenCoordinate.x, currentLong: screenCoordinate.y);
            },
            onTapListener: (screenCoordinate) async {
              pointAnnotationManager?.deleteAll();
              _createMarker(currentLat: screenCoordinate.x, currentLong: screenCoordinate.y);
              setState(()  {});
            },
          )
        );
      }