I am using flutter_map in conjunction with go_router. I have a container widget, which is stateful and, among other things, can save the map bounds for state restoration. It loads the initial bound from the widget and, if the widget is updated, it will move the map to match as well.
The deeplink is accessed in form of ?lat=51.5&lon=0.0&zoom=16
, which will cause the map to jump to the specified position.
Part of the code is below:
class AroundYouMapRoute extends GoRouteData {
final double? lat;
final double? lng;
final double? zoom;
// I would like to pass a LatLng object but it is not supported
// https://github.com/flutter/flutter/issues/110781
const AroundYouMapRoute({this.lat, this.lng, this.zoom});
@override
Widget build(BuildContext context, GoRouterState state) {
final initialPosition = lat?.chain((lat) => lng?.chain((lng) => LatLng(lat, lng)));
return AroundYouMapContainer(
initialPosition: initialPosition,
initialZoom: zoom,
route: this,
);
}
}
class AroundYouMapContainer extends StatefulHookConsumerWidget {
const AroundYouMapContainer({super.key, this.initialPosition, this.initialZoom, this.route});
final LatLng? initialPosition;
final double? initialZoom;
final AroundYouMapRoute? route;
@override
ConsumerState<AroundYouMapContainer> createState() => _AroundYouMapState();
}
class _AroundYouMapState extends ConsumerState<AroundYouMapContainer> with RestorationMixin<AroundYouMapContainer> {
late final boundsRestorable = RestorableLatLngBoundsN(null);
bool _mapReady = false;
late final mapController = MapController();
LatLngBounds? get bounds => boundsRestorable.value;
set bounds(LatLngBounds? value) {
boundsRestorable.value = value;
}
@override
Widget build(BuildContext context) {
void onMove(MapCamera camera) {
final bounds = camera.visibleBounds;
this.bounds = bounds;
// TODO: I need something to update the route / URL in the browser without navigating away
}
void onMapReady() {
_mapReady = true;
this.bounds = mapController.camera.visibleBounds;
}
// ...contains a map which uses mapController, onMove and onMapReady
}
@override
String? get restorationId => 'AroundYou';
@override
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
registerForRestoration(boundsRestorable, 'bounds');
}
@override
void didUpdateWidget(AroundYouMapContainer oldWidget) {
super.didUpdateWidget(oldWidget);
if (_mapReady) {
mapController.move(
widget.initialPosition ?? mapController.camera.center,
widget.initialZoom ?? mapController.camera.zoom
);
}
}
@override
void dispose() {
mapController.dispose();
super.dispose();
}
}
I have read https://github.com/csells/go_router/discussions/342 but it is not useful, because it involves using `context.go()`. I have tried it, but there is an ill effect that, when I jump to another page, the map will be moved because of the animation, which triggers the `move()` callback, and it will do another `context.go()` and jump back to the map.
How can I make the URL change in the browser when I move the map, without adverse effects?