diff --git a/app/lib/widgets/choropleth_map.dart b/app/lib/widgets/choropleth_map.dart index 58b717ac3078caa4004c61ffb02b99c38b80ddbc..1d4c9542d38ae262f674e7e66545633104569872 100644 --- a/app/lib/widgets/choropleth_map.dart +++ b/app/lib/widgets/choropleth_map.dart @@ -28,6 +28,8 @@ class ChoroplethMap extends StatefulWidget { } class ChoroplethMapState extends State<ChoroplethMap> { + late final GlobalKey<ChoroplethMapState> _choroplethMapKey = GlobalKey(); + int selectedIndex = -1; // Subdivision/map tile index late MapShapeSource dataSource; late final MapZoomPanBehavior _zoomPanBehavior = MapZoomPanBehavior(); @@ -36,6 +38,12 @@ class ChoroplethMapState extends State<ChoroplethMap> { _initDataSource(); } + void resetZoom() { + setState(() { + _choroplethMapKey.currentState?.resetZoom(); + }); + } + @override void initState() { super.initState(); diff --git a/app/lib/widgets/main_layout.dart b/app/lib/widgets/main_layout.dart index e44453493fbb8b57e86f9ba7cc9d3eb1475b8f61..1d20c1e67e52bd16d961a4d4c178b178493c014f 100644 --- a/app/lib/widgets/main_layout.dart +++ b/app/lib/widgets/main_layout.dart @@ -32,19 +32,20 @@ class MapContainerWidget extends StatefulWidget { } class _MapContainerWidgetState extends State<MapContainerWidget> { + // Button state trackers bool isMinimized = true; // Quick view box state tacker - bool satLayer = false; // Satellite layer visibility state bool osmLayer = false; // OSM layer visibility state - bool isSatTapped = false; // Satellite button tap state tracker bool isMapTapped = false; // OSM button tap state tracker + bool infoLayer = false; // Additional color information visibility + bool centerMap = false; // Map centering button state tracker - bool infoLayer = false; // Additional color legend visibility - + // Initialise selected measurement to arbitrary value Measurement? selectedMeasurement = selectedMeasurements[0]; + final GlobalKey<ChoroplethMapState> _choroplethMapKey = GlobalKey(); - // Initialise lastUpdate variable from persistent storage if server fetch fails + /// Initialise lastUpdate variable from persistent storage if server fetch fails Future<void> checkAndSetLastUpdate() async { if (lastUpdate == null) { final prefs = await SharedPreferences.getInstance(); @@ -76,6 +77,13 @@ class _MapContainerWidgetState extends State<MapContainerWidget> { }); } + /// Reset the map zoom and centering + void resetZoom() { + setState(() { + _choroplethMapKey.currentState?.resetZoom(); + }); + } + @override Widget build(BuildContext context) { // Initialise selectedMarker to first element in markerList @@ -109,6 +117,7 @@ class _MapContainerWidgetState extends State<MapContainerWidget> { child: Padding( padding: const EdgeInsets.all(15.0), // Padding around map child: ChoroplethMap( + key: _choroplethMapKey, relation: widget.relation, measurements: widget.measurements, subdivisions: widget.subdivisions, @@ -227,9 +236,42 @@ class _MapContainerWidgetState extends State<MapContainerWidget> { ), ), ), - Positioned( // Color info button + Positioned( // Recenter map button top: 130, right: 10, + child: GestureDetector( + onTapDown: (_) { + setState(() { + centerMap = true; + }); + }, + onTapUp: (_) { + setState(() { + centerMap = false; + }); + resetZoom(); // Reset the map zoom + }, + onTapCancel: () { + setState(() { + centerMap = false; + }); + }, + child: Container( + padding: const EdgeInsets.all(8), + decoration: centerMap ? const BoxDecoration( // Add decoration only while pressed + shape: BoxShape.circle, + color: Colors.grey, + ) : null, + child: const Icon( + Icons.center_focus_strong, + color: Colors.white54, + ), + ), + ), + ), + Positioned( // Color info button + top: 170, + right: 10, child: GestureDetector( onTap: () { setState(() {