Flutter_map: pop up on marker clicked

Created on 10 Dec 2018  路  14Comments  路  Source: fleaflet/flutter_map

I want to have pop up on marker clicked like simple map example of leafletjs site but however I couldn't find such feature
here is js code provided in leaflet website:

L.marker([51.5, -0.09]).addTo(map)
    .bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
    .openPopup();

Most helpful comment

This is a bit of quick code to highlight what I mean...it will need some tweaking, change centerlatlng to be wherever the original marker is in latlng

bool popupShown = false; // at top of class

Then in build function somewhere...

```
List markerList = [];

/// The Main Marker
Container testMarkerContainer = new Container(
child: new GestureDetector(
behavior: HitTestBehavior.opaque,
child: new Icon(Icons.location_on, size: 20.0,
color: Colors.orange),
onTap: () { /// So we want to display the marker if tapped
popupShown = true;
setState(() {});
},)

);

/// Add it to our MarkerList
markerList.add(
new Marker(
width: 80.0,
height: 80.0,
point: centerLatLng, // a latlng of where you want it
builder: (ctx) =>
testMarkerContainer,
),
);

/// Here's the popup
Container popupContainer = new Container(
  child: new GestureDetector(
    behavior:  HitTestBehavior.opaque,
    onTap: () { popupShown = false; setState(() {}); }, // remove the popup if we click on it
    child: new Card(
      child: Column(
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
           ListTile(
            leading: Icon(Icons.album),
            title: Text('This is at:' ),
            subtitle: Text(centerLatLng.toString()),
          ),
        ],
      ),
    ),
  ),
);

/// Add the Marker to our list if we previously clicked it and set popupshown=true
if( popupShown == true) {
  markerList.add(
    new Marker(
      width: 150.0,
      height: 150.0,
      point: centerLatLng, // Probably want to add an offset so it appears above the point, rather than over it
      builder: (ctx) => popupContainer,
    )
  );
}

/// Set our markerlist as the markers for MarkerLayerOptions
MarkerLayerOptions markerLayerOptions = new MarkerLayerOptions(
  markers: markerList,
);`

Then in the FlutterMap code, add the markerLayerOptions in the layers list;

All 14 comments

+1 for me

As a workaround, are you able to do this as part of your Marker widget?

@johnpryan marker widget don't have such option which supports pop up

Can't you do something like have a marker with a GestureDetector and then pop up a card or something when onTap is registered ?

In google maps this is called a Marker InfoWindow - I think that it is typically implemented using a marker adapter. This is probably something that we would have to add support for by submitting a PR if no one else is working on it.

We don鈥檛 plan to add support for this directly to the map because i think it can be implemented using @ibrierly鈥檚 suggestion

@dazza5000 It would be great if you submit a PR for this feature I need it in my project asap thanks

@ibrierley can you please provide an example for your solution? sorry I am new to flutter I couldn't understand your solution correctly.

@DanialV You might be able to use https://docs.flutter.io/flutter/material/DropdownMenuItem-class.html in the Marker

This is a bit of quick code to highlight what I mean...it will need some tweaking, change centerlatlng to be wherever the original marker is in latlng

bool popupShown = false; // at top of class

Then in build function somewhere...

```
List markerList = [];

/// The Main Marker
Container testMarkerContainer = new Container(
child: new GestureDetector(
behavior: HitTestBehavior.opaque,
child: new Icon(Icons.location_on, size: 20.0,
color: Colors.orange),
onTap: () { /// So we want to display the marker if tapped
popupShown = true;
setState(() {});
},)

);

/// Add it to our MarkerList
markerList.add(
new Marker(
width: 80.0,
height: 80.0,
point: centerLatLng, // a latlng of where you want it
builder: (ctx) =>
testMarkerContainer,
),
);

/// Here's the popup
Container popupContainer = new Container(
  child: new GestureDetector(
    behavior:  HitTestBehavior.opaque,
    onTap: () { popupShown = false; setState(() {}); }, // remove the popup if we click on it
    child: new Card(
      child: Column(
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
           ListTile(
            leading: Icon(Icons.album),
            title: Text('This is at:' ),
            subtitle: Text(centerLatLng.toString()),
          ),
        ],
      ),
    ),
  ),
);

/// Add the Marker to our list if we previously clicked it and set popupshown=true
if( popupShown == true) {
  markerList.add(
    new Marker(
      width: 150.0,
      height: 150.0,
      point: centerLatLng, // Probably want to add an offset so it appears above the point, rather than over it
      builder: (ctx) => popupContainer,
    )
  );
}

/// Set our markerlist as the markers for MarkerLayerOptions
MarkerLayerOptions markerLayerOptions = new MarkerLayerOptions(
  markers: markerList,
);`

Then in the FlutterMap code, add the markerLayerOptions in the layers list;

another way

...
return Marker(
      width: 40.0,
      height: 40.0,
      point: LatLng(latLong[0], latLong[1]),
      builder: (ctx) => MapMarker(x),
    );
  });
}



class MapMarker extends StatefulWidget {
  final X x;

  MapMarker(this.x);

  @override
  _MapMarkerState createState() => _MapMarkerState();
}

class _MapMarkerState extends State<MapMarker> {
  final key = new GlobalKey();

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        final dynamic tooltip = key.currentState;
        tooltip.ensureTooltipVisible();
      },
      child: Tooltip(
        key: key,
        message: widget.x.name,
        textStyle: textStyle,
        padding: EdgeInsets.fromLTRB(10, 10, 10, 15),
        decoration: BoxDecoration(
          color: Colors.white,
        ),
        child: Container(
          child: SvgPicture.asset(
            'assets/svg/map_mark_green_icon.svg',
          ),
        ),
      ),
    );
  }
}

another way

...
return Marker(
      width: 40.0,
      height: 40.0,
      point: LatLng(latLong[0], latLong[1]),
      builder: (ctx) => MapMarker(x),
    );
  });
}



class MapMarker extends StatefulWidget {
  final X x;

  MapMarker(this.x);

  @override
  _MapMarkerState createState() => _MapMarkerState();
}

class _MapMarkerState extends State<MapMarker> {
  final key = new GlobalKey();

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        final dynamic tooltip = key.currentState;
        tooltip.ensureTooltipVisible();
      },
      child: Tooltip(
        key: key,
        message: widget.x.name,
        textStyle: textStyle,
        padding: EdgeInsets.fromLTRB(10, 10, 10, 15),
        decoration: BoxDecoration(
          color: Colors.white,
        ),
        child: Container(
          child: SvgPicture.asset(
            'assets/svg/map_mark_green_icon.svg',
          ),
        ),
      ),
    );
  }
}

what is X?

@klaszlo8207
in my case x was a model which I passed to the Widget BUT x does not have any deal with th popup thing, you can ignore it, just take the idea and change the things that u need to adapt to your case.

Here is my drop-in widget created with the previous answers (thanks!). Simply pass your existing marker child as the MarkerWithTooltip child:

widget

class MarkerWithTooltip extends StatefulWidget {
  final Widget child;
  final String tooltip;
  final Function onTap;

  MarkerWithTooltip({@required this.child, this.tooltip, this.onTap});

  @override
  _MapMarkerState createState() => _MapMarkerState();
}

class _MapMarkerState extends State<MarkerWithTooltip> {
  final key = new GlobalKey();

  @override
  Widget build(BuildContext context) {
    return InkWell(
        onTap: () {
          final dynamic tooltip = key.currentState;
          tooltip.ensureTooltipVisible();
          widget.onTap();
        },
        child: Tooltip(
          key: key,
          message: widget.tooltip,
          child: widget.child,
        ));
  }
}

use

Marker(
          point: // the position
          builder: (BuildContext context) {
            return MarkerWithTooltip(
                child: Image.asset(
                    'marker.png'),
                tooltip: "the tooltip text",
                onTap: onTap);
          });
Was this page helpful?
0 / 5 - 0 ratings

Related issues

EdHubbell picture EdHubbell  路  4Comments

igaurab picture igaurab  路  5Comments

rktvsiim picture rktvsiim  路  5Comments

jasonleung101 picture jasonleung101  路  3Comments

zozeei picture zozeei  路  4Comments