Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pop up on marker clicked #184

Closed
DanialV opened this issue Dec 10, 2018 · 18 comments
Closed

pop up on marker clicked #184

DanialV opened this issue Dec 10, 2018 · 18 comments

Comments

@DanialV
Copy link

DanialV commented Dec 10, 2018

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();
@ganisback
Copy link

+1 for me

@johnpryan
Copy link
Collaborator

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

@DanialV
Copy link
Author

DanialV commented Dec 12, 2018

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

@ibrierley
Copy link
Collaborator

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

@dazza5000
Copy link

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.

@johnpryan
Copy link
Collaborator

We don’t plan to add support for this directly to the map because i think it can be implemented using @ibrierly’s suggestion

@DanialV
Copy link
Author

DanialV commented Dec 12, 2018

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

@DanialV
Copy link
Author

DanialV commented Dec 12, 2018

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

@johnpryan
Copy link
Collaborator

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

@ibrierley
Copy link
Collaborator

ibrierley commented Dec 12, 2018

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<Marker> 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;

@tarekbazine
Copy link

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',
          ),
        ),
      ),
    );
  }
}

@klaszlo8207
Copy link

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?

@tarekbazine
Copy link

@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.

@HugoHeneault
Copy link
Contributor

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);
          });

@altilunium
Copy link

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',
          ),
        ),
      ),
    );
  }
}

Thank you. Worked really well for me.

Additional notes : you have to place the MarkerLayer() at the very last of FlutterMap children.

For example, this one will work :

children:[
   TileLayer(),
   PolygonLayer(),
   PolygonLayer(),
   CurrentLocationLayer(),
   MarkerLayer()

While this one will not work :

children:[
   TileLayer(),
   PolygonLayer(),
   PolygonLayer(),
   MarkerLayer(),
   CurrentLocationLayer(),

Likely because the tap event only enters the topmost layer.

@ragavendra
Copy link

Does the solution(s) here still work? I am trying this with the latest copy of this repository in the example\lib\pages\markers.dart and apparently builder parameter doesn't seem to be valid any more.

Marker signature now

  const Marker({
    this.key,
    required this.point,
    required this.child,
    this.width = 30,
    this.height = 30,
    this.alignment,
    this.rotate,
  });

@ibrierley
Copy link
Collaborator

Just use child instead of the builder ?

@ragavendra
Copy link

Just use child instead of the builder ?

Yes, that worked for me for the MarkerWithTooltip snippet above. I will try with others when I get a chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants