import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:sliding_up_panel/sliding_up_panel.dart'; import 'package:latlong2/latlong.dart'; import 'package:geocoding/geocoding.dart'; import 'package:geocode/geocode.dart'; import 'dart:async'; import 'package:fast_network_navigation/modules/navigation.dart'; class MapPage extends StatefulWidget { @override _MapPageState createState() => _MapPageState(); } class Debounce { Duration delay; Timer? _timer; Debounce( this.delay, ); call(void Function() callback) { _timer?.cancel(); _timer = Timer(delay, callback); } dispose() { _timer?.cancel(); } } class _MapPageState extends State { GeoCode geoCode = GeoCode(); final mapController = MapController(); String _currentCityName = "..."; final Debounce _debounce = Debounce(Duration(seconds: 3)); void _setCurrentCityName() async { if (mapController.camera.zoom < 9) { return; // Don't bother if the view is too wide } var currentCoordinates = mapController.camera.center; String? city; try{ List placemarks = await placemarkFromCoordinates(currentCoordinates.latitude, currentCoordinates.longitude); city = placemarks[0].locality.toString(); } catch (e) { debugPrint("Error: $e"); try { Address address = await geoCode.reverseGeocoding(latitude: currentCoordinates.latitude, longitude: currentCoordinates.longitude); if (address.city == null || address.city.toString().contains("Throttled!")){ throw Exception("Probably rate limited"); } city = address.city.toString(); } catch (e) { debugPrint("Error: $e"); } } if (city != null) { setState(() { _currentCityName = city!; }); } else { _debounce(() async {_setCurrentCityName();}); } } @override Widget build(BuildContext context) { final ThemeData theme = Theme.of(context); return SlidingUpPanel( renderPanelSheet: false, panel: _floatingPanel(theme), collapsed: _floatingCollapsed(theme), body: FlutterMap( mapController: mapController, options: MapOptions( initialZoom: 11, initialCenter: LatLng(51.509364, -0.128928), onMapReady: () { mapController.mapEventStream.listen((evt) {_debounce(() async {_setCurrentCityName();});}); // And any other `MapController` dependent non-movement methods }, ), children: [ openStreetMapTileLayer, ], ), ); } Widget _floatingCollapsed(ThemeData theme){ return Container( decoration: BoxDecoration( color: theme.canvasColor, borderRadius: BorderRadius.only(topLeft: Radius.circular(24.0), topRight: Radius.circular(24.0)), ), child: Greeting(theme) ); } Widget _floatingPanel(ThemeData theme){ return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(24.0)), boxShadow: [ BoxShadow( blurRadius: 20.0, color: theme.shadowColor, ), ] ), child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: SingleChildScrollView( child: Column( children: [ Greeting(theme), Text("Got a lot to do today! Here is a rundown:"), ...loadDestinations(), ], ), ), ), ), ); } Widget Greeting (ThemeData theme) { return Center( child: Text( "Explore ${_currentCityName}", style: TextStyle(color: theme.primaryColor, fontSize: 24.0, fontWeight: FontWeight.bold), ), ); } } TileLayer get openStreetMapTileLayer => TileLayer( urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', userAgentPackageName: 'flutter_map', ); // Add a pin to the map