rorystephenson / flutter_map_marker_popup

Popups for flutter_map markers
BSD 3-Clause "New" or "Revised" License
103 stars 84 forks source link

Create example for passing data to the popup by extending Marker #3

Closed rorystephenson closed 4 years ago

rorystephenson commented 4 years ago

It's possible to pass whatever data you want to the Popup by extending Marker and adding the data to the embedded popup. It would be nice to create an example for this.

flogaribal commented 4 years ago

Hi @rorystephenson,

Thanks for your plugin and for your short explanation about how to give extra data to a Marker, I did not think about it before reading it here! I created a small example below to illustrate your points, if it does not match with what you wanted to know, feel free to tell me and I will remove/edit it.

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_marker_popup/flutter_map_marker_popup.dart';
import 'package:latlong/latlong.dart';

void main() => runApp(MyApp());
const double MARKER_SIZE = 25;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Marker with additional data example',
      home: MapPage(),
    );
  }
}

class MapPage extends StatefulWidget {
  MapPage({Key key}) : super(key: key);

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

class _MapPageState extends State<MapPage> {
  final PopupController _popupLayerController = PopupController();
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FlutterMap(
        options: MapOptions(
          plugins: <MapPlugin>[PopupMarkerPlugin()],
          center: LatLng(48.857661, 2.295135),
          zoom: 13.0,
          interactive: true,
          onTap: (_) => _popupLayerController.hidePopup(),
        ),
        layers: <LayerOptions>[
          TileLayerOptions(
            urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
            subdomains: <String>['a', 'b', 'c'],
          ),
          PopupMarkerLayerOptions(
            markers: <Marker>[
              MonumentMarker(
                monument: Monument(
                  name: 'Eiffel Tower',
                  imagePath:
                      'https://cdn.lifestyleasia.com/wp-content/uploads/2019/10/21224220/Winer-Parisienne.jpg',
                  lat: 48.857661,
                  long: 2.295135,
                ),
              ),
              Marker(
                anchorPos: AnchorPos.align(AnchorAlign.top),
                point: LatLng(48.859661, 2.305135),
                height: MARKER_SIZE,
                width: MARKER_SIZE,
                builder: (BuildContext ctx) => Icon(Icons.shop),
              ),
            ],
            popupController: _popupLayerController,
            popupBuilder: (_, Marker marker) {
              if (marker is MonumentMarker) {
                return MonumentMarkerPopup(monument: marker.monument);
              }
              return Card(child: const Text('Not a monument'));
            },
          ),
        ],
      ),
    );
  }
}

class Monument {
  Monument({this.name, this.imagePath, this.lat, this.long});

  final String name;
  final String imagePath;
  final double lat;
  final double long;
}

class MonumentMarker extends Marker {
  MonumentMarker({@required this.monument})
      : super(
          anchorPos: AnchorPos.align(AnchorAlign.top),
          height: MARKER_SIZE,
          width: MARKER_SIZE,
          point: LatLng(monument.lat, monument.long),
          builder: (BuildContext ctx) => Icon(Icons.camera_alt),
        );

  final Monument monument;
}

class MonumentMarkerPopup extends StatelessWidget {
  const MonumentMarkerPopup({Key key, this.monument}) : super(key: key);
  final Monument monument;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 200,
      child: Card(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(15),
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Image.network(monument.imagePath, width: 200),
            Text(monument.name),
            Text('${monument.lat}-${monument.long}'),
          ],
        ),
      ),
    );
  }
}
rorystephenson commented 4 years ago

Finally got around to adding this. Thanks a lot @flogaribal !

https://github.com/rorystephenson/flutter_map_marker_popup/commit/697c38df46916e2c77d74db54f3b7a94fc76f909

giroprotagonist commented 2 years ago

Hello after a few days of trying to pass values to markers I finally came and found this thread. Unfortunately the example is not updated to null safety. I attempted to do this but ran into some issues with the _popupLayerController stating that "The argument type 'void Function(TapPosition)' can't be assigned to the parameter type 'void Function(TapPosition, LatLng)?'." The latlong package needed to be changed to latlong2 to support null safety, but I'm not sure if this is what's causing the problem as I'm a fairly new programmer. Long story short, is there any way this example can be updated to Null Safety. I'm quite looking forward to being able to pass values to my markers but my programming skill is coming up short. Long story short, any way this example could be updated to work with null safety or the error I'm getting? Or any suggestions period? Thanks !

rorystephenson commented 2 years ago

@giroprotagonist thanks for pointing that out! It should be fixed now.

giroprotagonist commented 2 years ago

Ah that was easy enough, thank you, very much appreciated!