I'm trying to get the map rotation (bearing) but can't find it with the map controller.
Using currently google_maps_flutter: ^1.1.1 and flutter: 1.22
You can get the real time updated bearing by following steps:
listen to changes of the location using:
double mainBearing = 15.0;
location.onLocationChanged.listen((locationLib.LocationData cLoc) {
//You can get the bearing of current location by using
mainBearing = cLoc.heading
//Or you can do newCameraPoistion here with new bearing
_controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(cLoc.latitude, cLoc.longitude),
zoom: zoomCamera,
bearing: cLoc.heading,
),
),
);
}
You can do that by using this geolocator plugin and then you can get your position with:
Position position = await Geolocator.getCurrentPosition();
and then update map with:
controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: 16,
bearing: position.heading,
),
),
),
Found it: CameraPosition has bearing:
controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
bearing: location.heading.value,
target: LatLng(location.latitude ?? 51.4,
location.longitude ?? 4.4),
zoom: 18),
),
Actually I found what I was looking for. There is the onCameMove callback on GoogleMap constructor and it receives current CameraPosition as its argument. It has the bearing, target, tilt and zoom fields.
This way I can be aware of changes to the map's bearing at anytime.
PS: This function is executed repeatedly while the user is moving the map and should not perform expensive operations.
You can find it on the properties of CameraPosition function from your GoogleMaps library.
_googleMapController!.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
target: LatLng(cLoc.latitude!, cLoc.longitude!),
bearing: cLoc.heading!,
tilt: 30,
zoom: 18,
)))
and you can also call this from location.onLocationChanged.listen((LocationData cLoc) {}
And that's it.
Related
I am using Stream Builder that sends api request after some seconds and fetch coordinates (lat, lng).
I want to update the map location (camera position & marker) on newly fetch coordinates.
But Camera position is updating and not focusing on new coordinates.
My google map widget is inside of stream builder and in which we are passing data through snapshot
e.g latlng = LatLng(snapshot.data['lat'],snapshot.data['lng']) to markers: SetMarker( markers, markerID, latlng, ), & initialCameraPosition: CameraPosition( target: latlng, zoom: 9.0, )
The GoogleMaps widget on Flutter does have the attribute initialCameraPosition but as the name says this is just an initial value, if you want to update the map once this has loaded i'd recommend the use of the callback onMapCreated, where you can use the controller to animate to a certain position.
Doing so would look something like this:
onMapCreated: (GoogleMapController controller) {
controller.animateCamera(
CameraUpdate.newCameraPosition(CameraPosition(
target: LatLng(snapshot.data['lat'],
snapshot.data['lng']),
zoom: 12)));
setState((){});
}
Hope this helps! ;)
I'm trying to get the user current location, but I got this error on l.latitude and l.longitude
The argument type 'double?' can't be assigned to the parameter type 'double'.
void _onMapCreated(GoogleMapController _cntlr) {
_controller = _cntlr;
_location.onLocationChanged.listen((l) {
_controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(l.latitude, l.longitude),
zoom: 15,
),
),
);
});
}
The error you get is from null-safety, the type double? means that it could be either a double, or null, but your parameter only accepts a double, and no null.
For this, you can "force" the use of 'non-null' variable by adding a ! at the end of your variable, but be careful when doing this.
CameraPosition(
target: LatLng(l.latitude!, l.longitude!),
zoom: 15,
)
You can learn more about null-safety syntax and principles on the official documentation: https://flutter.dev/docs/null-safety
You could also null check the local variables, thereby making your code null safe:
when location changes
if (lat/lon are not null) {
animate camera
}
So something like this might work:
void _onMapCreated(GoogleMapController _cntlr) {
_controller = _cntlr;
_location.onLocationChanged.listen((l) {
if (l.latitude != null && l.longitude != null) {
_controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(l.latitude, l.longitude),
zoom: 15,
),
),
);
}
});
}
Logically, it wouldn't make sense to animate to a null latitude/longitude, so you can skip that listener call altogether if that's the case.
Filip talks about this situation & handling here.
The above solution did not work for me, if it did not work for you too, the problem will be because both of the variables you are trying to access must have a null check so just do this instead,
CameraPosition(
target: LatLng(l!.latitude!, l!.longitude!),
zoom: 15,
)
simply add ! in front of l and another to the front of latitude or longitude, this will perfectly fix the code
I found this library: https://pub.dev/packages/flutter_map_picker
I looked through his code and tried figuring out how he initiates drawing. What he accomplishes is far more complicated than I need, and I can't figure out the first step of what he did. I also don't want to take the guy's code. Can anyone explain how to accomplish this?
I just want to be able to circle objects on my map. There seems to be a polyline solution but it's just straight lines from a list of coordinates, not exactly what I'm looking for.
A Stack widget with GoogleMap and CustomPaint will let you draw anything you want on top of the map.
Stack(
children: <Widget>[
_position == null
? Text('Waiting for location . .')
: GoogleMap(
liteModeEnabled: false,
compassEnabled: true,
mapType: MapType.hybrid,
markers: Set<Marker>.of(markers.values),
initialCameraPosition: CameraPosition(
target: LatLng(_position.latitude, _position.longitude),
zoom: 17,
tilt: 0,
),
onMapCreated: (GoogleMapController controller) {
_mapController = controller;
// trigger initial update and paint of landmarks
_updateLandmarks();
},
onCameraMove: (CameraPosition position) {
_updateLandmarks();
},
),
CustomPaint(
foregroundPainter: MapPainter(_landmarksMap),
),
],
)
You have to convert map coordinates to device screen coordinates. Google has a cookbook on how to do that except it does not work in Flutter since the map plugin does not expose the complete API. But there is a way to do it of course.
void _updateLandmarks() async {
double dpi = MediaQuery.of(context).devicePixelRatio;
LatLngBounds bounds = await _mapController.getVisibleRegion();
ScreenCoordinate topRight = await _mapController.getScreenCoordinate(bounds.northeast);
ScreenCoordinate bottomLeft = await _mapController.getScreenCoordinate(bounds.southwest);
_landmarksMap.values.forEach((element) async {
ScreenCoordinate sc = await _mapController.getScreenCoordinate(LatLng(element.pos.latitude, element.pos.longitude));
element.screenPoint.x = ((sc.x - bottomLeft.x) / dpi).floor();
element.screenPoint.y = ((sc.y - topRight.y) / dpi).floor();
});
setState(() {});
}
You can read here for more details: https://aperico.com/google-maps-with-custom-paint-in-flutter/
I'm a novice in Flutter, and I encountered an issue with google maps plugin. I watched a couple of tutorials in order to get the current position of the camera and Most of them was using GoogleMapController.cameraPosition.target. I think they deleted this method from the controller(Since it is still on the development stage). Is there any other way of getting the current position of the camera?
If you are using the google_maps_flutter package:
The GoogleMap widget have the onCameraMove function that returns the CameraPosition while dragging the map or moving the camera.
To do this, you'll need to create a callback function called _getCameraPosition(CameraPosition cameraPosition which will be invoked when onCameraMove is called. For example:
void _getCameraPosition(CameraPosition cameraPosition) {
// You can do whatever you want with cameraPosition here
log("cameraPosition: " + cameraPosition.target.toString());
}
Then, you'll need to put the _getCameraPosition function to the onCameraMove field on GoogleMap widget, like this:
GoogleMap(
onCameraMove: _getCameraPosition, // pass it here
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(-33.86882, 151.209296),
zoom: 12,
),
),
As a result, you will get a LatLng value in the debug console. For example:
cameraPosition: LatLng(-33.8940124943736, 151.2027569487691)
I'm pretty new in Flutter. It is amazing. I'm working on small app usign google maps. I have 6 points (Markers) and need to recognize which one was selected.
I've added ontap event into every marker with i-index (i = 0..5). When I tap/click on marker I always get 6. It should be 0..5 based on marker.
Thanx a lot, Gabriel
i=0;
marker.clear();
for (myPoint mar in globals.historia.items) {
print(i.toString());
marker.add(Marker(
markerId: MarkerId(i.toString()),
position: mar.pos,
draggable: false,
consumeTapEvents: true,
onTap: () {
print("Marker_id-${i.toString()}");
},
));
i++;
}
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: myposition,
zoom: 17.0,
),
polylines: road,
markers: Set.of(marker),
)
When onTap() is triggered it calls i with its last value that's == 6, that's why every time you tap on a marker, the print method prints 6.
i is a global variable, that has its own address, so the print method will search for the value on that address every time onTap is called.
I propose this solution - replace youtr print method inside onTap with this : print("Marker_id-${globals.historia.items.indexOf(mar)}")
mar is a local variable inside the for in loop, and its value has never changed, so he will point on the same value, onTap will behave as you want.