Flutter - Google Maps doesn´t wait to Location - google-maps

I´m trying to show a map with current location. For do this i used Location and Google Map plugins (last version).
I have a code similar to:
var lng, lat;
#override
initState() {
super.initState();
loading = true;
getLocation();
}
Future getLocation() async {
final location = Location();
var currentLocation = await location.getLocation();
setState(() {
lat = currentLocation.latitude;
lng = currentLocation.longitude;
loading=false;
});
}
loading==false ? GoogleMap(
mapType: MapType.hybrid,
myLocationButtonEnabled: true,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(lat, lng),
zoom: 15.0,
)):null,
When we go the view with map a error appear around 1s (then view load properly) with this error in the console
I/flutter (15567): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════ I/flutter
(15567): The following assertion was thrown building
HomePageScreen(dirty, dependencies: I/flutter (15567):
[_LocalizationsScope-[GlobalKey#78c30], MediaQuery], state:
_HomePageScreen#9c9d2): I/flutter (15567): 'package:google_maps_flutter/src/location.dart': Failed assertion:
line 17 pos 16: 'latitude != I/flutter (15567): null': is not true.
I debug it and the error is relative simple: The Location plugin load latitude and longitude slow , Google Maps plugin load more fast. So we have a error.
The question is: How can i force Google map to wait location and longitude from Location plugin?

Show an empty Container() or any loading indicator while your lat and lng is null.
lat == null || lng == null
? Container()
: GoogleMap(
mapType: MapType.hybrid,
myLocationButtonEnabled: true,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(lat, lng),
zoom: 15.0,
),
);

you can display a loader until you get your location,
var lng, lat;
#override
initState() {
super.initState();
loading = true;
getLocation();
}
Future getLocation() async {
final location = Location();
var currentLocation = await location.getLocation();
setState(() {
lat = currentLocation.latitude;
lng = currentLocation.longitude;
loading=false;
});
}
loading==false ? GoogleMap(
mapType: MapType.hybrid,
myLocationButtonEnabled: true,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(lat, lng),
zoom: 15.0,
)):CircularProgressIndicator(),

You can also try this, and get rid of the empty Container.
GoogleMap(
mapType: MapType.hybrid,
myLocationButtonEnabled: true,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(lat ?? 0, lng ?? 0), // so if lat, lng is null, we use 0 as placeholder.
zoom: 15.0,
),
)

Related

Flutter: How to place the mylocation button on Google Maps at different positions?

I'm using Google Maps and by default the myLocation button shows up on the topRight corner. I want it at the bottom right corner.
I can't seem to have any property inside GoogleMap widget
GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: true,
initialCameraPosition: CameraPosition(
target: _currentLocation,
zoom: 11.0,
),
onMapCreated: _onMapCreated,
),
Try using FloationgButton
GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
myLocationEnabled: true,
),
floatingActionButton: FloatingActionButton.extended(
onPressed: _currentLocation,
label: Text('My Location'),
icon: Icon(Icons.location_on),
),
);
}
also set with the current location
void _currentLocation() async {
final GoogleMapController controller = await _controller.future;
LocationData currentLocation;
var location = new Location();
try {
currentLocation = await location.getLocation();
} on Exception {
currentLocation = null;
}
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
bearing: 0,
target: LatLng(currentLocation.latitude, currentLocation.longitude),
zoom: 17.0,
),
));
}

how to animate google map view when change lat and lng?

I added google map inside column.
my inspector like this:
Scaffold
- stack
- singlechildscrollview
- form
- container
- padding
- column
- sizedbox
- googlemap
SizedBox(
width: width,
height:height * .4,
child: GoogleMap(
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>[
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer())].toSet(),
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(lat, lng),
zoom: 15),
onCameraMove: (_)=>CameraPosition(
target: LatLng(lat, lng),
zoom: 15),
markers: Set<Marker>.of(<Marker>[
Marker(
markerId: MarkerId('id'),
position: LatLng(lat, lng),
icon: BitmapDescriptor.defaultMarker,
),
]),
onMapCreated: (GoogleMapController controller) {
setState(() {
controller.animateCamera(CameraUpdate.newLatLng(
LatLng(lat, lng),
));
});
},
)),
Google map search
RaisedButton(
onPressed: _handlePressButton,
child: Text("Search places"),
),
Future<void> _handlePressButton() async {
Prediction p = await PlacesAutocomplete.show(
context: context,
apiKey: kGoogleApiKey,
mode: Mode.overlay,
);
displayPrediction(p);
}
Future<void> displayPrediction(Prediction p) async {
if (p != null) {
PlacesDetailsResponse detail =
await _places.getDetailsByPlaceId(p.placeId);
setState(() {
lat = detail.result.geometry.location.lat;
lng = detail.result.geometry.location.lng;
});
}
}
After change lat and LNG map is not animated but the marker changed.. how to animate google map view?
this is how you would go about it
final GoogleMapController controller = await mapController;
mapCcontroller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
bearing: 0,
target: LatLng(lat, lon),
zoom: 16.0,
),
));

How does drop pins with long press on google map with flutter?

I'm new to flutter.
I'm trying to drop pins on map with flutter,
Here I got the current location with geolocator package and set a marker
GoogleMap(
onMapCreated: (controller){
mapController=controller ;
},
mapType: _currentMapType,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target:_center,
zoom: 11.0,
),
markers: {
//Marker for current Location
Marker(
markerId: MarkerId("marker"),
position: LatLng(currentPosition.latitude, currentPosition.longitude),
infoWindow: InfoWindow(title: 'Current Location'),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed)
)
},
),
I was recently working on this code, it may help you.
1.- First define the markers in this way (do it as a global variable):
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
2.- Create the Google Maps widget:
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Stack(
children: [Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
mapType: _defaultMapType,
myLocationEnabled: true,
myLocationButtonEnabled: true,
initialCameraPosition: _currentposition,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
compassEnabled: true,
tiltGesturesEnabled: false,
onLongPress: (latlang) {
_addMarkerLongPressed(latlang); //we will call this function when pressed on the map
},
markers: Set<Marker>.of(markers.values), //all markers are here
)
)]
),
);
}
3.- Create the function (method) '_addMarkerLongPressed':
Future _addMarkerLongPressed(LatLng latlang) async {
setState(() {
final MarkerId markerId = MarkerId("RANDOM_ID");
Marker marker = Marker(
markerId: markerId,
draggable: true,
position: latlang, //With this parameter you automatically obtain latitude and longitude
infoWindow: InfoWindow(
title: "Marker here",
snippet: 'This looks good',
),
icon: BitmapDescriptor.defaultMarker,
);
markers[markerId] = marker;
});
//This is optional, it will zoom when the marker has been created
GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newLatLngZoom(latlang, 17.0));
}
I hope I've helped :)

can we initialCameraPosition in GoogleMap - Flutter

how can we setup initial camera positions in googleMap i.e. instead of hard code lat/lang (below code)
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(30.666, 76.8127),
zoom: 15
),
onMapCreated: _onMapCreated,
myLocationEnabled: true,
mapType: MapType.hybrid,
compassEnabled: true,
trackCameraPosition: true,
)
I just want my current location lat/lang instead of hard coded values
Use location package.
Here is an example.
var currentLocation = LocationData;
var location = new Location();
// Platform messages may fail, so we use a try/catch PlatformException.
try {
currentLocation = await location.getLocation();
} on PlatformException catch (e) {
if (e.code == 'PERMISSION_DENIED') {
error = 'Permission denied';
}
currentLocation = null;
}
And then
var location = new Location(); location.onLocationChanged().listen((LocationData currentLocation) {
print(currentLocation.latitude);
print(currentLocation.longitude);
})

Iterate markers Google Flutter maps

I´m trying to iterate markers in new google flutter map.
I retrieve the array of the coordinates with a web service, then i iterate the elements and get the index that have latitude and longitude.
for (int i = 0; i < list.length; i++) {
mapController.addMarker(MarkerOptions(position: list[0].values.elementAt(i)))));
}
And the map options.
GoogleMapController mapController;
GoogleMap(
onMapCreated: (GoogleMapController mapController) {
mapController = mapController;
},
options: GoogleMapOptions(
mapType: MapType.satellite,
myLocationEnabled :true,
cameraPosition: CameraPosition(
target: LatLng(40.347022, -3.750381), zoom: 5.0),
),
),
I suppose that mapController should take the coordinates that i put in the for loop, but doesn't work. The console return
The method 'addMarker' was called on null.
So the question is, how can i add multiple markers dynamically using google flutter map package?
Also i tried this simple code and works, so the error is occurred when adding markers.
GoogleMapController mapController;
GoogleMap(
onMapCreated: (GoogleMapController mapController) {
mapController = mapController;
mapController.addMarker(MarkerOptions(
position:LatLng(40.347022, -3.750381),
infoWindowText: InfoWindowText("Title", "Content"),
//icon:
));
mapController.addMarker(MarkerOptions(
position:LatLng(43.321871, -3.006887),
infoWindowText: InfoWindowText("Title", "Content"),
//icon:
));
},
options: GoogleMapOptions(
mapType: MapType.satellite,
myLocationEnabled :true,
cameraPosition: CameraPosition(
target: LatLng(40.347022, -3.750381), zoom: 5.0),
),
),
UPDATE 2
I found this example code. This is exactly that i want but i can´t repeat this code, return this error
https://github.com/gerryhigh/Flutter-Google-Maps-Demo/blob/master/lib/venues.dart
NoSuchMethodError: The getter 'className' was called on null.
I call an instance of Google maps in the main build function.Like this:
return GoogleMap(
onMapCreated: _onMapCreated,
options: GoogleMapOptions(
cameraPosition: CameraPosition(
target: _center1,
zoom: 11.0,
),
),
);
Inside the "_onMapCreated" function is where I have the iterator:
widget.model.allItems.forEach((item) {
//print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
print(item.lat);
var newItem = LatLng(double.parse(item.lat), double.parse(item.lon));
mapController.addMarker(
MarkerOptions(
icon: BitmapDescriptor.fromAsset(assetName),
position: newItem,
),
);
});
This is working for me.
In the first example GoogleMapController paramater and your local variable have the same name, so basically, local variable becomes shadowed and you're assigning function parameter value to itself. Renaming one of these two should resolve the issue.
void populateOrder(Item item) async {
if (item != null) {
for (int i = 0; i < item.feature.length; i++) {
var position = item.feature[i];
if (position != null) {
try {
if (double.parse(position.latitude) != null &&
double.parse(position.longitude) != null) {
mapController.clearMarkers().then((value){
mapController.addMarker(
MarkerOptions(
position: LatLng(double.parse(position.latitude),
double.parse(position.longitude)),
infoWindowText: InfoWindowText(position.schet, ""),
icon: BitmapDescriptor.defaultMarker,
),
);
});
}
} catch (e) {
print(e);
}
}
}
}
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
populateOrder(itemize);
Future.delayed(Duration(seconds: 6));
}
The library was updated: this is how I was able to show multiple markers on the map.
Completer<GoogleMapController> _controller = Completer();
// initial camera position
CameraPosition _cameraPos;
// A map of markers
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
// function to generate random ids
int generateIds() {
var rng = new Random();
var randomInt;
randomInt = rng.nextInt(100);
print(rng.nextInt(100));
return randomInt;
}
//call this function in initstate
// I'm getting a json Object with locations from an
// external api
buildMarkers() {
for (var i = 0; i < gridItem.locations.length; i++) {
var markerIdVal = generateIds();
final MarkerId markerId = MarkerId(markerIdVal.toString());
final Marker marker = Marker(
markerId: markerId,
position: LatLng(
gridItem.locations[i].latitude,
gridItem.locations[i].longitude,
),
infoWindow: InfoWindow(title: gridItem.locations[i].place, snippet: gridItem.locations[i].region),
);
// you could do setState here when adding the markers to the Map
markers[markerId] = marker;
}
print("Length:: + ${markers.length}");
}
// your Googlemaps Widget somewhere in your widget tree
GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _cameraPos,
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>[Factory<OneSequenceGestureRecognizer>(()=>ScaleGestureRecognizer())].toSet(),
markers: Set<Marker>.of(markers.values),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);}),