Skip to content
This repository has been archived by the owner on May 8, 2023. It is now read-only.

Commit

Permalink
Merge branch 'stateful_markers'
Browse files Browse the repository at this point in the history
  • Loading branch information
synw committed Jan 15, 2020
2 parents d1d8320 + 67071a1 commit 624776c
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 1 deletion.
5 changes: 5 additions & 0 deletions example/lib/index.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ class IndexPage extends StatelessWidget {
text: "Markers",
link: "/markers",
),
MainButton(
icon: Icons.edit_location,
text: "Stateful markers",
link: "/stateful_markers",
),
MainButton(
icon: Icons.map,
text: "Tile layer",
Expand Down
2 changes: 2 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import 'package:flutter/material.dart';
import 'geojson.dart';
import 'index.dart';
import 'markers.dart';
import 'stateful_markers.dart';
import 'tile_layer.dart';

final Map<String, Widget Function(BuildContext)> routes = {
'/': (BuildContext context) => IndexPage(),
'/markers': (BuildContext context) => MarkersPage(),
'/geojson': (BuildContext context) => GeoJsonPage(),
'/tile_layer': (BuildContext context) => TileLayerPage(),
'/stateful_markers': (BuildContext context) => StatefulMarkersPage(),
};

void main() => runApp(MyApp());
Expand Down
120 changes: 120 additions & 0 deletions example/lib/stateful_markers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import 'dart:async';

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

class Place {
Place(this.name, this.point);

final String name;
final LatLng point;
}

class _StatefulMarkersPageState extends State<StatefulMarkersPage> {
MapController mapController;
StatefulMapController statefulMapController;
StreamSubscription<StatefulMapControllerStateChange> sub;

final List<Place> places = [
Place("Notre-Dame", LatLng(48.853831, 2.348722)),
Place("Montmartre", LatLng(48.886463, 2.341169)),
Place("Champs-Elysées", LatLng(48.873932, 2.294821)),
Place("Chinatown", LatLng(48.827393, 2.361897)),
Place("Tour Eiffel", LatLng(48.85801, 2.294713))
];

final _markersOnMap = <Place>[];
bool ready = false;

void addMarker(BuildContext context) {
for (final place in places) {
if (!_markersOnMap.contains(place)) {
print("Adding marker ${place.name}");
statefulMapController.addStatefulMarker(
name: place.name,
statefulMarker: StatefulMarker(
//anchorAlign: AnchorAlign.bottom,
height: 80.0,
width: 150.0,
state: <String, dynamic>{"showText": false},
point: place.point,
builder: (BuildContext context, Map<String, dynamic> state) {
Widget w;
final markerIcon = IconButton(
icon: const Icon(Icons.location_on),
onPressed: () => statefulMapController.mutateMarker(
name: place.name,
property: "showText",
value: !(state["showText"] as bool)));
if (state["showText"] == true) {
w = Column(children: <Widget>[
markerIcon,
Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Text(place.name, textScaleFactor: 1.3))),
]);
} else {
w = markerIcon;
}
return w;
}));
_markersOnMap.add(place);
return;
}
}
}

@override
void initState() {
mapController = MapController();
statefulMapController = StatefulMapController(mapController: mapController);
statefulMapController.onReady.then((_) => setState(() => ready = true));
sub = statefulMapController.changeFeed.listen((change) => setState(() {}));
super.initState();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: FlutterMap(
mapController: mapController,
options: MapOptions(
center: LatLng(48.853831, 2.348722),
zoom: 11.0,
),
layers: [
TileLayerOptions(
urlTemplate:
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
subdomains: ['a', 'b', 'c']),
MarkerLayerOptions(
markers: statefulMapController.markers,
),
],
),
),
floatingActionButton: ready
? FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => addMarker(context),
)
: const Text(""),
);
}

@override
void dispose() {
sub.cancel();
super.dispose();
}
}

class StatefulMarkersPage extends StatefulWidget {
@override
_StatefulMarkersPageState createState() => _StatefulMarkersPageState();
}
1 change: 1 addition & 0 deletions lib/map_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ library map_controller;

export 'src/controller.dart';
export 'src/models.dart';
export 'src/models.dart';
export 'src/tile_layer/layers.dart';
export 'src/tile_layer/layers.dart';
export 'src/tile_layer/tile_layers_bar.dart';
Expand Down
17 changes: 16 additions & 1 deletion lib/src/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'state/markers.dart';
import 'state/polygons.dart';
import 'state/tile_layer.dart';
import 'types.dart';
import 'state/stateful_markers.dart';

/// The map controller
class StatefulMapController {
Expand All @@ -31,6 +32,8 @@ class StatefulMapController {
_linesState = LinesState(notify: notify);
_polygonsState = PolygonsState(notify: notify);
_mapState = MapState(mapController: mapController, notify: notify);
_statefulMarkersState =
StatefulMarkersState(mapController: mapController, notify: notify);
if (customTileLayer != null) {
tileLayerType = TileLayerType.custom;
}
Expand Down Expand Up @@ -64,6 +67,7 @@ class StatefulMapController {
LinesState _linesState;
PolygonsState _polygonsState;
TileLayerState _tileLayerState;
StatefulMarkersState _statefulMarkersState;

final Completer<void> _readyCompleter = Completer<void>();
final _subject = PublishSubject<StatefulMapControllerStateChange>();
Expand All @@ -84,8 +88,19 @@ class StatefulMapController {
/// The map center value
LatLng get center => mapController.center;

/// The stateful markers present on the map
Map<String, StatefulMarker> get statefulMarkers =>
_statefulMarkersState.statefulMarkers;

void addStatefulMarker({String name, StatefulMarker statefulMarker}) =>
_statefulMarkersState.addStatefulMarker(name, statefulMarker);

void mutateMarker({String name, String property, dynamic value}) =>
_statefulMarkersState.mutate(name, property, value);

/// The markers present on the map
List<Marker> get markers => _markersState.markers;
List<Marker> get markers =>
_markersState.markers..addAll(_statefulMarkersState.markers);

/// The markers present on the map and their names
Map<String, Marker> get namedMarkers => _markersState.namedMarkers;
Expand Down
36 changes: 36 additions & 0 deletions lib/src/models.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,40 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong/latlong.dart';

typedef StatefulMarkerBuidler = Widget Function(
BuildContext, Map<String, dynamic>);

class StatefulMarker {
StatefulMarker(
{@required this.point,
@required this.state,
@required this.builder,
this.width = 30.0,
this.height = 30.0,
this.anchorAlign = AnchorAlign.center});

final LatLng point;
final double width;
final double height;
final AnchorAlign anchorAlign;
final Map<String, dynamic> state;
final StatefulMarkerBuidler builder;

Marker get marker => _build();

void mutate(String name, dynamic value) => state[name] = value;

Marker _build() {
return Marker(
anchorPos: AnchorPos.align(anchorAlign),
point: point,
width: width,
height: height,
builder: (BuildContext c) => builder(c, state));
}
}

/// The type of the controller change
enum MapControllerChangeType {
Expand Down
34 changes: 34 additions & 0 deletions lib/src/state/stateful_markers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_map/flutter_map.dart';

import '../models.dart';

class StatefulMarkersState {
/// Provide a [MapController]
StatefulMarkersState({@required this.mapController, @required this.notify})
: assert(mapController != null);

/// The Flutter Map controller
final MapController mapController;

/// The notification function
final Function notify;

final _statefulMarkers = <String, StatefulMarker>{};
final _namedMarkers = <String, Marker>{};

List<Marker> get markers => _namedMarkers.values.toList();
Map<String, StatefulMarker> get statefulMarkers => _statefulMarkers;

void addStatefulMarker(String name, StatefulMarker statefulMarker) {
_statefulMarkers[name] = statefulMarker;
_namedMarkers[name] = statefulMarker.marker;
notify("updateMarkers", statefulMarker, addStatefulMarker,
MapControllerChangeType.markers);
}

void mutate(String name, String property, dynamic value) {
_statefulMarkers[name].mutate(property, value);
addStatefulMarker(name, _statefulMarkers[name]);
}
}

0 comments on commit 624776c

Please sign in to comment.