How do I display user location as soon as permission is granted?
421
I was receiving an target != null error and this was fixed with adding CircularProgressIndicator()
children: <Widget>[
Container(
decoration: BoxDecoration(
// Login Box
image: _buildBackgroundImage(),
),
),
_userLocation == null
? CircularProgressIndicator()
: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: // required parameter that sets the starting camera position. Camera position describes which part of the world you want the map to point at.
CameraPosition(
target: _userLocation,
zoom: 14.5,
tilt: 0.0), //LatLng(53.467125, -2.233966)
scrollGesturesEnabled: true,
tiltGesturesEnabled: true,
compassEnabled: true,
rotateGesturesEnabled: true,
myLocationEnabled: true,
mapType: _currentMapType,
zoomGesturesEnabled: true,
),
],
Author by
Andrew Stevenson
Updated on December 15, 2022Comments
-
Andrew Stevenson over 1 year
I am creating a map application and I have an issue, where the app won't show the user location once permission is granted.
Packages Used
- permission_handler
- google_maps_flutter.dart'
I have got the location permission thing sorted, but the app doesn't show the user location as soon as the permissions have been granted. If I re-run the app, then it does.
This is frustrating the hell out of me and I would appreciate it, if somebody could show me how to display the users' current location once the permissions have been granted?
Here is the code
import 'package:flutter/material.dart'; import 'package:ManchesterMaps/models/locales.dart'; import 'package:ManchesterMaps/widgets/drawers/map_drawer.dart'; import 'package:ManchesterMaps/widgets/home_pages/my_places/list_places.dart'; import 'package:ManchesterMaps/widgets/home_pages/settings/preferences.dart'; import 'package:ManchesterMaps/widgets/home_pages/the_map/the_map.dart'; import 'package:ManchesterMaps/widgets/home_pages/uni_security/uni_security_info.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:circular_bottom_navigation/circular_bottom_navigation.dart'; import 'package:circular_bottom_navigation/tab_item.dart'; import './theme.dart' as Theme; void main() => runApp(App()); class App extends StatefulWidget { @override _AppState createState() => _AppState(); } class _AppState extends State<App> with WidgetsBindingObserver { PageController controller = PageController(); int selected = 0; //BottomBar list List<TabItem> tabItems = List.of([ new TabItem(Icons.home, "Campus Map", Theme.UniColors.primaryColour[500], labelStyle: TextStyle( color: Theme.UniColors.primaryColour[500], fontWeight: FontWeight.normal)), new TabItem(Icons.search, "Search", Theme.UniColors.primaryColour[500], labelStyle: TextStyle( color: Theme.UniColors.primaryColour[500], fontWeight: FontWeight.normal)), new TabItem(Icons.place, "My Places", Theme.UniColors.primaryColour[500], labelStyle: TextStyle( color: Theme.UniColors.primaryColour[500], fontWeight: FontWeight.normal)), new TabItem( Icons.security, "Security Info", Theme.UniColors.primaryColour[500], labelStyle: TextStyle( color: Theme.UniColors.primaryColour[500], fontWeight: FontWeight.normal)), new TabItem(Icons.settings, "Settings", Theme.UniColors.primaryColour[500], labelStyle: TextStyle( color: Theme.UniColors.primaryColour[300], fontWeight: FontWeight.normal)), ]); // Show Map Page CircularBottomNavigationController _navigationController = new CircularBottomNavigationController(0); @override Widget build(BuildContext context) { //Locale myLocale = Localizations.localeOf(context); return MaterialApp( localizationsDelegates: [ // A class which loads the translations from JSON files const AppLocalizationsDelegate(), // Built-in localization of basic text for Material widgets GlobalMaterialLocalizations.delegate, // Built-in localization for text direction LTR/RTL GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], supportedLocales: [ const Locale('en', ''), const Locale('fr', ''), const Locale('ar', ''), const Locale('de', ''), const Locale('es', ''), const Locale('hi', ''), ], onGenerateTitle: (BuildContext context) => AppLocalizations.of(context).title, color: Theme.UniColors.primaryColour[300], theme: Theme.uniThemeData, home: Scaffold( body: Stack( children: <Widget>[ PageView( children: <Widget>[ Container( child: TheMap(), ), Container( child: Center(child: Text("Page 2")), ), Container( child: ListPlaces(), ), Container( child: UniSecurityInfo(), ), Container( child: Preferences(), ), ], controller: controller, onPageChanged: (num) { controller.animateToPage( _navigationController.value, curve: Curves.ease, duration: Duration(milliseconds: 300), ); }, ), ], ), extendBody: true, bottomNavigationBar: CircularBottomNavigation( tabItems, controller: _navigationController, selectedCallback: (int selected) { _navigationController.value = selected; switch (selected) { case 0: { controller.animateToPage(0, curve: Curves.easeIn, duration: Duration(milliseconds: 300)); break; } case 1: { controller.animateToPage(1, curve: Curves.easeIn, duration: Duration(milliseconds: 300)); break; } case 2: { controller.animateToPage(2, curve: Curves.easeIn, duration: Duration(milliseconds: 300)); break; } case 3: { controller.animateToPage(3, curve: Curves.easeIn, duration: Duration(milliseconds: 300)); break; } case 4: { controller.animateToPage(4, curve: Curves.easeIn, duration: Duration(milliseconds: 300)); break; } } }, ), drawer: MapDrawer(), ), ); } } import 'dart:async'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:geolocator/geolocator.dart'; class TheMap extends StatefulWidget { TheMap({Key key}) : super(key: key); _TheMapState createState() => _TheMapState(); } class _TheMapState extends State<TheMap> with WidgetsBindingObserver { PermissionStatus _status; Completer<GoogleMapController> _mapController = Completer(); LatLng _centre; Position currentLocation; MapType _currentMapType = MapType.normal; FutureOr<GoogleMapController> get controller => null; // check permissions @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); // Check location permission has been granted PermissionHandler() .checkPermissionStatus(PermissionGroup .locationWhenInUse) //check permission returns a Future .then(_updateStatus); // handling in callback to prevent blocking UI } //double distanceInMeters = await Geolocator().distanceBetween(52.2165157, 6.9437819, 52.3546274, 4.8285838); // method that is called on map creation and takes a MapController as a parameter void _onMapCreated(GoogleMapController controller) { PermissionHandler() .checkPermissionStatus(PermissionGroup .locationWhenInUse) //check permission returns a Future .then(_updateStatus); // handling in callback to prevent blocking UI _mapController.complete( controller); // manages camera function (position, animation, zoom). } Future<Position> locateUser() async { return Geolocator() .getCurrentPosition(desiredAccuracy: LocationAccuracy.high); } //TODO: Get Users' location getUserLocation() async { currentLocation = await locateUser(); setState(() { _centre = LatLng(currentLocation.latitude ?? 53.467125, currentLocation.longitude ?? -2.233966); }); print('centre $_centre'); } @override Widget build(BuildContext context) { return Stack( children: <Widget>[ GoogleMap( onMapCreated: _onMapCreated, initialCameraPosition: // required parameter that sets the starting camera position. Camera position describes which part of the world you want the map to point at. CameraPosition( target: LatLng(53.467125, -2.233966), zoom: 14.5, tilt: 0.0), scrollGesturesEnabled: true, tiltGesturesEnabled: true, compassEnabled: true, rotateGesturesEnabled: true, myLocationEnabled: true, mapType: _currentMapType, zoomGesturesEnabled: true, ), ], ); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } // check permissions when app is resumed // this is when permissions are changed in app settings outside of app void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { PermissionHandler() .checkPermissionStatus(PermissionGroup.locationWhenInUse) .then(_updateStatus); } print("STATE -> $state"); } /*void _askPermission() { PermissionHandler().requestPermissions( [PermissionGroup.locationWhenInUse]).then(_onStatusRequested); }*/ void _onStatusRequested(Map<PermissionGroup, PermissionStatus> statuses) { final status = statuses[PermissionGroup.locationWhenInUse]; if (status != PermissionStatus.granted) { // On iOS if "deny" is pressed, open App Settings PermissionHandler().openAppSettings(); } else { //_updateStatus(status); print("STATUS -> $status"); } } void _updateStatus(PermissionStatus status) { if (status != _status) { // check status has changed setState(() { _status = status; // update _onMapCreated(controller); }); } else { if (status != PermissionStatus.granted) { print("REQUESTING PERMISSION"); PermissionHandler().requestPermissions( [PermissionGroup.locationWhenInUse]).then(_onStatusRequested); } } } }
Am I missing something really obvious here?
Any help is extremely appreciated.
thanks