import 'dart:async'; import 'dart:convert'; import 'dart:ui'; import 'package:android_intent/android_intent.dart'; import 'package:chat/utils/loading_builder.dart'; import 'package:chat/utils/log.dart'; import 'package:chat/utils/screen_shot.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:provider/provider.dart'; import 'location_provider.dart'; import 'location_result.dart'; import 'package:http/http.dart' as http; class MapPicker extends StatefulWidget { final LatLng initialCenter; final String apiKey; final bool requiredGPS; const MapPicker({ Key key, this.initialCenter, this.apiKey, this.requiredGPS, }) : super(key: key); @override MapPickerState createState() => MapPickerState(); } class MapPickerState extends State { Completer mapController = Completer(); GlobalKey rootWidgetKey = GlobalKey(); LatLng _lastMapPosition; Position _currentPosition; String _address; // void _onToggleMapTypePressed() { // final MapType nextType = // MapType.values[(_currentMapType.index + 1) % MapType.values.length]; // setState(() => _currentMapType = nextType); // } // this also checks for location permission. Future _initCurrentLocation() async { Position currentPosition; try { currentPosition = await Geolocator() .getCurrentPosition(desiredAccuracy: LocationAccuracy.best); d("position = $currentPosition"); setState(() => _currentPosition = currentPosition); } on PlatformException catch (e) { currentPosition = null; d("_initCurrentLocation#e = $e"); } if (!mounted) return; setState(() => _currentPosition = currentPosition); if (currentPosition != null) moveToCurrentLocation( LatLng(currentPosition.latitude, currentPosition.longitude)); } @override void initState() { super.initState(); _initCurrentLocation(); } @override void dispose() { rootWidgetKey = null; super.dispose(); } @override Widget build(BuildContext context) { if (widget.requiredGPS) { _checkGps(); _checkGeolocationPermission(); } return Scaffold( body: Builder(builder: (context) { if (_currentPosition == null && widget.requiredGPS) return const Center(child: CircularProgressIndicator()); return buildMap(); }), ); } Widget buildMap() { return Center( child: Stack( children: [ GoogleMap( onMapCreated: (GoogleMapController controller) { mapController.complete(controller); _lastMapPosition = widget.initialCenter; LocationProvider.of(context) .setLastIdleLocation(_lastMapPosition); }, initialCameraPosition: CameraPosition( target: widget.initialCenter, zoom: 18.0, ), onCameraMove: (CameraPosition position) { _lastMapPosition = position.target; }, onCameraIdle: () async { LocationProvider.of(context) .setLastIdleLocation(_lastMapPosition); }, myLocationEnabled: true, myLocationButtonEnabled: true), // _MapFabs( // onToggleMapTypePressed: _onToggleMapTypePressed, // ), pin(), locationCard(), ], ), ); } Widget locationCard() { return Align( alignment: Alignment.bottomCenter, child: Padding( padding: const EdgeInsets.fromLTRB(8, 8, 8, 24), child: Card( child: Padding( padding: const EdgeInsets.all(8), child: Consumer( builder: (context, locationProvider, _) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible( flex: 20, child: FutureLoadingBuilder( future: getAddress(locationProvider.lastIdleLocation), mutable: true, loadingIndicator: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(), ], ), builder: (context, address) { _address = address; return Column( mainAxisSize: MainAxisSize.min, children: [ Text( address ?? 'Unnamed place', textScaleFactor: 1.0, style: TextStyle( fontSize: 18, ), ), ], ); }), ), Spacer(), FloatingActionButton( onPressed: () async { var capture = await ScreenShot.takeScreenshotImage(); Navigator.of(context).pop({ 'location': LocationResult( latLng: locationProvider.lastIdleLocation, address: _address, screen: capture), }); }, child: Icon(Icons.send, color: Colors.white), ), ], ); }), ), ), ), ); } Future getAddress(LatLng latLng) async { try { /* var placeMarks = await Geolocator() .placemarkFromCoordinates(latLng.latitude, latLng.longitude); if (placeMarks == null) { return null; } var place = placeMarks.first; print('place ${place.toJson()}'); return place.name; */ var endPoint = 'https://maps.googleapis.com/maps/api/geocode/json?latlng=${latLng?.latitude},${latLng?.longitude}&key=${widget.apiKey}'; var response = jsonDecode((await http.get(endPoint)).body); return response['results'][0]['formatted_address']; } catch (e) { print(e); } return null; } Center pin() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.place, size: 56, color: Colors.lightBlue), Container( decoration: ShapeDecoration( shadows: [ BoxShadow( color: Colors.black38, blurRadius: 4, ), ], shape: CircleBorder( side: BorderSide( width: 4, color: Colors.transparent, ), ), ), ), SizedBox(height: 56), ], ), ); } Future moveToCurrentLocation(LatLng currentLocation) async { var controller = await mapController.future; controller.animateCamera(CameraUpdate.newCameraPosition( CameraPosition(target: currentLocation, zoom: 18.0), )); } var dialogOpen; Future _checkGeolocationPermission() async { var geolocationStatus = await Geolocator().checkGeolocationPermissionStatus(); if (geolocationStatus == GeolocationStatus.denied && dialogOpen == null) { d('showDialog'); dialogOpen = showDialog( context: context, barrierDismissible: false, builder: (context) { return AlertDialog( title: Text('Access to location denied'), content: Text('Allow access to the location services.'), actions: [ FlatButton( child: Text('Ok'), onPressed: () { Navigator.of(context, rootNavigator: true).pop(); _initCurrentLocation(); dialogOpen = null; }, ), ], ); }, ); //} else if (geolocationStatus == GeolocationStatus.disabled) { } else if (geolocationStatus == GeolocationStatus.granted) { d('GeolocationStatus.granted'); if (dialogOpen != null) { Navigator.of(context, rootNavigator: true).pop(); dialogOpen = null; } } } Future _checkGps() async { if (!(await Geolocator().isLocationServiceEnabled())) { if (Theme.of(context).platform == TargetPlatform.android) { showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return AlertDialog( title: Text("Can't get current location"), content: Text('Please make sure you enable GPS and try again'), actions: [ FlatButton( child: Text('Ok'), onPressed: () { final AndroidIntent intent = AndroidIntent( action: 'android.settings.LOCATION_SOURCE_SETTINGS'); intent.launch(); Navigator.of(context, rootNavigator: true).pop(); }, ), ], ); }, ); } } } } /* class _MapFabs extends StatelessWidget { const _MapFabs({ Key key, @required this.onToggleMapTypePressed, }) : assert(onToggleMapTypePressed != null), super(key: key); final VoidCallback onToggleMapTypePressed; @override Widget build(BuildContext context) { return Container( alignment: Alignment.topRight, margin: const EdgeInsets.only(top: 64, right: 8), child: Column( children: [ FloatingActionButton( onPressed: onToggleMapTypePressed, materialTapTargetSize: MaterialTapTargetSize.padded, mini: true, child: const Icon(Icons.layers, size: 28, color: Colors.white), heroTag: "layers", ), ], ), ); } }*/