How do I display user location as soon as permission is granted? - google-maps

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

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,
),
],

Related

how to get a data from HtmlElementView in flutter-web

i am having a trouble with adding webview in side flutter web
import 'package:flutter/material.dart';
import 'package:flutter/src/foundation/key.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'dart:ui' as ui;
import 'dart:html' as html;
class UserAddress3 extends StatefulWidget {
const UserAddress3({Key? key}) : super(key: key);
#override
State<UserAddress3> createState() => _UserAddress3State();
}
class _UserAddress3State extends State<UserAddress3> {
#override
void initState() {
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'html.iframeElement',
(int viewId) => html.IFrameElement()
..src = 'https://daum_postcode_mobile'
..style.width = '100%'
..style.height = '100%'
..style.border = 'none');
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('주소 검색'),
backgroundColor: Colors.white,
),
body: Container(
child: HtmlElementView(
viewType: 'html.iframeElement',
),
),
);
}
}
'https://daum_postcode_mobile' this link leads to where we can find a address
so the web-view displays fine but i can't have a datas if I click the address
I thought it would work as same as how Webview worked in Flutter App but it seems totaly different...
Is there any one knows how to get datas from HtmleElementView???
p.s and this is my codes which used in my app
class KakaoAddress extends StatefulWidget {
#override
_KakaoAddressState createState() => _KakaoAddressState();
}
class _KakaoAddressState extends State<KakaoAddress> {
final Completer<WebViewController> _controller = Completer<WebViewController>();
#override
Widget build(context) {
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(
color: Colors.black,
),
titleSpacing: 0.0,
elevation: 0.0,
title: const Text(
'주소 검색',
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w700, color: Colors.black),
),
actions: <Widget>[
SampleMenu(),
],
backgroundColor: Colors.white,
),
body: Builder(builder: (context) {
return WebView(
initialUrl: 'https://daum_postcode_mobile',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
// ignore: prefer_collection_literals
javascriptChannels: <JavascriptChannel>[
_toasterJavascriptChannel(context),
].toSet(),
);
}),
);
}
JavascriptChannel _toasterJavascriptChannel(context) {
return JavascriptChannel(
name: 'Daum',
onMessageReceived: (JavascriptMessage message) async {
final myJsonAsString = message.message;
dynamic received = json.decode(myJsonAsString);
dynamic address = received["address"];
Navigator.pop(context, address);
});
}
}
class SampleMenu extends StatelessWidget {
#override
Widget build(context) {
return FutureBuilder<WebViewController>(
builder: (context, AsyncSnapshot<WebViewController> controller) {
return IconButton(
icon: Icon(
Icons.close,
size: 25.0,
),
onPressed: () {
Navigator.pop(context);
});
},
);
}
}
I made something similar, which may help you. I handled mouse clicks performed inside HtmlElementView, with Dart code, the following way:
In the code passed to ui.platformViewRegistry.registerViewFactory() I used DOM manipulation to attach a listener to the onClick event of an element.
You can do the same with a custom event and trigger that event anytime from Javascript to call and pass data to the Dart side.

Flutter Google Maps: How can you change maptype after runtime?

I am trying to change from normal to satellite when pressing a button as shown below, but i get an error that setMapType does not exist.
mapController.setMapType(MapType.satellite);
Anyone knows what I am doing wrong?
Create a MapType variable:
MapType _currentMapType = MapType.normal;
Reference this variable when calling your Google Map widget:
googleMap = new GoogleMap(
mapType: _currentMapType,
//etc
Create a floating button widget to toggle map types:
floatingActionButton: FloatingActionButton(
child: Icon(Icons.layers),
onPressed: ()=>
{
setState(() {
_currentMapType = (_currentMapType == MapType.normal) ? MapType.satellite : MapType.normal;
});
},
heroTag: null,
),
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:search_map_place/search_map_place.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
String apiKEY;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Search Map Place Demo',
home: MapSample(),
);
}
}
class MapSample extends StatefulWidget {
#override
State<MapSample> createState() => MapSampleState();
}
class MapSampleState extends State<MapSample> {
Completer<GoogleMapController> _mapController = Completer();
final CameraPosition _initialCamera = CameraPosition(
target: LatLng(-20.3000, -40.2990),
zoom: 14.0000,
);
var maptype = MapType.normal;
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
body: Stack(
children: <Widget>[
GoogleMap(
mapType: maptype,
initialCameraPosition: _initialCamera,
onMapCreated: (GoogleMapController controller) {
_mapController.complete(controller);
},
),
],
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.white,
foregroundColor: Colors.black,
child: const Icon(Icons.my_location),
onPressed: () {
setState(() {
this.maptype=MapType.satellite;
});
},
),
);
}
}

Google maps flutter user location

it does not even show the request for permission to access the users location
enter image description here
i am working on a sort of a delivery application but for good upon request just like uber, the code below is to access the users location upon loading .The problem is the code does not show any errors but does not show google maps after loading it just shows white background.
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:isntadelivery/Signin.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:permission_handler/permission_handler.dart' as Thendelo;
import 'package:fluttertoast/fluttertoast.dart';
import 'package:permission_handler/permission_handler.dart';
// import 'package';
class Homepage extends StatefulWidget {
Homepage({Key key}) : super(key: key);
#override
_HomepageState createState() => _HomepageState();
}
class _HomepageState extends State<Homepage> {
GoogleMapController _controller;
GoogleMapController mapController;
Position position;
Widget _child;
Future<void> getpermission() async {
PermissionStatus permission = await PermissionHandler()
.checkPermissionStatus(PermissionGroup.location);
if (permission == PermissionStatus.denied) {
await PermissionHandler()
.requestPermissions([PermissionGroup.locationAlways]);
}
var geolocater = new Geolocator();
GeolocationStatus geolocationStatus =
await geolocater.checkGeolocationPermissionStatus();
switch (geolocationStatus) {
case GeolocationStatus.denied:
showToast('denied');
break;
case GeolocationStatus.disabled:
showToast('disabled');
break;
case GeolocationStatus.restricted:
showToast('restricted');
break;
case GeolocationStatus.unknown:
showToast('unknown');
break;
case GeolocationStatus.granted:
showToast('Access granted');
_getCurrentLocation();
}
}
Set<Marker> _createMarker() {
return <Marker>[
Marker(
markerId: MarkerId('home'),
position: LatLng(position.latitude, position.longitude),
icon: BitmapDescriptor.defaultMarker,
infoWindow: InfoWindow(title: 'Current Location'))
].toSet();
}
void showToast(message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
// timeInSecFor Ios: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
void _setStyle(GoogleMapController controller) async {
String value = await DefaultAssetBundle.of(context)
.loadString('assets/map_style.json');
controller.setMapStyle(value);
}
Widget _mapWidget() {
return GoogleMap(
mapType: MapType.normal,
markers: _createMarker(),
initialCameraPosition: CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: 12.0,
),
onMapCreated: (GoogleMapController controller) {
_controller = controller;
// _controller.complete(controller);
_setStyle(controller);
},
);
}
//map style variable
void _getCurrentLocation() async {
Position res = await Geolocator().getCurrentPosition();
setState(() {
position = res;
_child = _mapWidget();
});
}
// singoutmethod
signOutGoogle() async {
await googleSignIn.signOut();
print("User Sign Out");
}
// firebase authorisation
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: _child,
drawer: Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
UserAccountsDrawerHeader(
accountName: new Text('Thabelo Mutshinyani'),
accountEmail: new Text('mutshinyanit#gmail.com'),
currentAccountPicture: new CircleAvatar(),
),
ListTile(
leading: Icon(Icons.person_outline),
title: Text('Update Profile'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.payment),
title: Text('payment details'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.settings),
title: Text('Settings'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.exit_to_app),
title: Text('LogOut'),
onTap: () {
signOutGoogle().whenComplete(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return Signin();
},
),
);
});
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
],
),
),
);
}
}
I think, based on your code, you should add the desiredAccuracy inside your _getCurrentLocation(). Like this:
void _getCurrentLocation() async {
Position res = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
setState(() {
position = res;
_child = _mapWidget();
});
}
And, to run the _getCurrentLocation() function at the beginning of the app, you should wrap it inside the initState method.
Inside your StatefulWidget class, add:
#override
void initState() {
_getCurrentLocation();
super.initState();
}
And then add the Location permission inside the device or emulator you're using. Add this line of codes inside the AndroidManifest.xml file.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
And my tips, cold restart your app (stop debug and debug it again from the beginning).
For IOS If you using this plugin, you also need to add permission in info plist like this, just copy and paste it.
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location when in use</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Always and when in use!</string>
<key>NSLocationUsageDescription</key>
<string>Older devices need location.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Can I have location always?</string>
For android
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
#override
void initState() {
_getCurrentLocation();
super.initState();
}

Flutter Google Maps not determining current location of device

I'm using Flutter's Geolocator and Google Maps packages to determine a device's location. I utilize the Circular Progress Bar to wait for the current location to be determined. Once determined, Google Maps loads with the device's location identified.
When the application loads, the circular progress bar is displayed but the map is not loaded despite the notification being displayed and accepted to use location services; the app hangs on the circular progress bar. I don't believe this to be an API issue as I have had success loading the map with coordinates specified in InitialCameraPosition.
Is the device's location not being determined which is the cause for the map to not load with the location indicated?
I've tried running the app on both Android emulator and a physical device without success.
Android Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="smartkart.app.com.coffee">
<!-- io.flutter.app.FlutterApplication is an android.app.Application
that
calls FlutterMain.startInitialization(this); in its onCreate
method.
In most cases you can leave this as-is, but you if you want to
provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:name="io.flutter.app.FlutterApplication"
android:label="coffee"
android:icon="#mipmap/ic_launcher">
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="API KEY HERE"/>
<activity../>
Maps Screen
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
class FirstScreen extends StatefulWidget {
const FirstScreen({Key key}) : super(key: key);
#override
State<FirstScreen> createState() => _FirstScreen();
}
class _FirstScreen extends State<FirstScreen> {
GoogleMapController mapController;
var currentLocation;
#override
void initState(){
super.initState();
Geolocator().getCurrentPosition().then((currloc){
currentLocation = currloc;
});
}
#override
Widget build(BuildContext context) {
return currentLocation == null ? Container(
alignment: Alignment.center,
child: Center(
child: CircularProgressIndicator(),
),
):
Stack(
children: <Widget>[
GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(currentLocation.latitude,
currentLocation.longitude), zoom: 10),
onMapCreated: _onMapCreated,
myLocationEnabled: true,
mapType: MapType.normal,
),
],
);
}
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
});
}
}
I expect the notification to use location services to appear while the circular progress bar is displayed. Once the location is determined, the InitialCameraPosition displays the device's location on the map.
Try the following code as a solution. You can modify the map widget to your use case:
import 'package:flutter/cupertino.dart';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class Map extends StatefulWidget {
#override
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
Completer<GoogleMapController> controller1;
//static LatLng _center = LatLng(-15.4630239974464, 28.363397732282127);
static LatLng _initialPosition;
final Set<Marker> _markers = {};
static LatLng _lastMapPosition = _initialPosition;
#override
void initState() {
super.initState();
_getUserLocation();
}
void _getUserLocation() async {
Position position = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
List<Placemark> placemark = await Geolocator().placemarkFromCoordinates(position.latitude, position.longitude);
setState(() {
_initialPosition = LatLng(position.latitude, position.longitude);
print('${placemark[0].name}');
});
}
_onMapCreated(GoogleMapController controller) {
setState(() {
controller1.complete(controller);
});
}
MapType _currentMapType = MapType.normal;
void _onMapTypeButtonPressed() {
setState(() {
_currentMapType = _currentMapType == MapType.normal
? MapType.satellite
: MapType.normal;
});
}
_onCameraMove(CameraPosition position) {
_lastMapPosition = position.target;
}
_onAddMarkerButtonPressed() {
setState(() {
_markers.add(
Marker(
markerId: MarkerId(_lastMapPosition.toString()),
position: _lastMapPosition,
infoWindow: InfoWindow(
title: "Pizza Parlour",
snippet: "This is a snippet",
onTap: (){
}
),
onTap: (){
},
icon: BitmapDescriptor.defaultMarker));
});
}
Widget mapButton(Function function, Icon icon, Color color) {
return RawMaterialButton(
onPressed: function,
child: icon,
shape: new CircleBorder(),
elevation: 2.0,
fillColor: color,
padding: const EdgeInsets.all(7.0),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _initialPosition == null ? Container(child: Center(child:Text('loading map..', style: TextStyle(fontFamily: 'Avenir-Medium', color: Colors.grey[400]),),),) : Container(
child: Stack(children: <Widget>[
GoogleMap(
markers: _markers,
mapType: _currentMapType,
initialCameraPosition: CameraPosition(
target: _initialPosition,
zoom: 14.4746,
),
onMapCreated: _onMapCreated,
zoomGesturesEnabled: true,
onCameraMove: _onCameraMove,
myLocationEnabled: true,
compassEnabled: true,
myLocationButtonEnabled: false,
),
Align(
alignment: Alignment.topRight,
child: Container(
margin: EdgeInsets.fromLTRB(0.0, 50.0, 0.0, 0.0),
child: Column(
children: <Widget>[
mapButton(_onAddMarkerButtonPressed,
Icon(
Icons.add_location
), Colors.blue),
mapButton(
_onMapTypeButtonPressed,
Icon(
IconData(0xf473,
fontFamily: CupertinoIcons.iconFont,
fontPackage: CupertinoIcons.iconFontPackage),
),
Colors.green),
],
)),
)
]),
),
);
}
}
You seem to be missing setState in your initState.
It should look like this:
#override
void initState(){
super.initState();
Geolocator().getCurrentPosition().then((currloc){
setState((){
currentLocation = currloc;
});
});
}
Use GeoLocator package with google_maps_flutter
Sample Code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
class MapScreen extends StatefulWidget {
#override
State<MapScreen> createState() => MapScreenState();
}
class MapScreenState extends State<MapScreen> {
LatLng initPosition = LatLng(0, 0); //initial Position cannot assign null values
LatLng currentLatLng= LatLng(0.0, 0.0); //initial currentPosition values cannot assign null values
LocationPermission permission = LocationPermission.denied; //initial permission status
Completer<GoogleMapController> _controller = Completer();
#override
void initState() {
super.initState();
getCurrentLocation();
checkPermission();
}
//checkPersion before initialize the map
void checkPermission() async{
permission = await Geolocator.checkPermission();
}
// get current location
void getCurrentLocation() async{
await Geolocator.getCurrentPosition().then((currLocation) {
setState(() {
currentLatLng =
new LatLng(currLocation.latitude, currLocation.longitude);
});
});
}
//call this onPress floating action button
void _currentLocation() async {
final GoogleMapController controller = await _controller.future;
getCurrentLocation();
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
bearing: 0,
target: currentLatLng,
zoom: 18.0,
),
));
}
//Check permission status and currentPosition before render the map
bool checkReady(LatLng? x, LocationPermission? y) {
if (x == initPosition || y == LocationPermission.denied || y == LocationPermission.deniedForever) {
return true;
} else {
return false;
}
}
#override
Widget build(BuildContext context) {
print(permission);
print("Current Location --------> " +
currentLatLng.latitude.toString() +
" " +
currentLatLng.longitude.toString());
return MaterialApp(
//remove debug banner on top right corner
debugShowCheckedModeBanner: false,
home: new Scaffold(
//ternary operator use for conditional rendering
body: checkReady(currentLatLng, permission)
? Center(child: CircularProgressIndicator())
//Stack : place floating action button on top of the map
: Stack(children: [
GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: false,
zoomControlsEnabled: false,
mapType: MapType.normal,
initialCameraPosition: CameraPosition(target: currentLatLng),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
//Positioned : use to place button bottom right corner
Positioned(
bottom: 0,
right: 0,
child: Container(
margin: EdgeInsets.all(15),
child: FloatingActionButton(
onPressed: _currentLocation,
child: Icon(Icons.location_on)),
),
),
]),
),
);
}
}

Flutter google_maps_flutter can't able to change MapType by PopupMenuButton

I'm just playing with new Google Map package of Flutter.
I want to change MapType of the map like, hybrid, satellite, none and etc by using of PopupMenuButton. Below are my code.
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapPage extends StatefulWidget {
#override
_MapPageState createState() => _MapPageState();
}
class _MapPageState extends State<MapPage> {
GoogleMapController mapController;
List arrMapTyep = [
{'title': 'none', 'value': MapType.none},
{'title': 'hybrid', 'value': MapType.hybrid},
{'title': 'normal', 'value': MapType.normal},
{'title': 'satellite', 'value': MapType.satellite},
{'title': 'terrain', 'value': MapType.terrain}
];
MapType currentMapType = MapType.normal;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Google Map"),
actions: <Widget>[
PopupMenuButton(
icon: Icon(Icons.more_vert),
initialValue: currentMapType,
onSelected: (value) {
setState(() {
currentMapType = value;
});
},
itemBuilder: (BuildContext context) => _setupAllMapType()
)
],
),
body: Container(
child: GoogleMap(
onMapCreated: _onMapCreated,
options: GoogleMapOptions(
mapType: currentMapType,
compassEnabled: true,
myLocationEnabled: true,
cameraPosition: CameraPosition(
target: LatLng(37.785834, -122.406417),
zoom: 16,
)
),
),
),
);
}
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
});
}
List<PopupMenuItem> _setupAllMapType() {
List<PopupMenuItem> temArr = List();
for (var i = 0; i < arrMapTyep.length; i++) {
temArr.add(
PopupMenuItem(
value: arrMapTyep[i]['value'],
child: Text(arrMapTyep[i]['title']),
),
);
}
return temArr;
}
}
I called setState but can work it.
I am not sure if it is too late to answer this, but in case someone like me stumbles upon this question;
Real time change in MapType, can be achieved using a setState() call upon currentMapType variable. I have implemented this in my application and it works smooth like butter!
Hope it helps. Happy Flutter'ing!
Quick reference (to change Normal map type to Satellite map type):
RaisedButton(
child: Text("Satellite"),
onPressed: () {
setState(() {
currentMapType = MapType.satellite;
});
},
)