I have created a Google Maps widget with markers and polylines with the code below.
Everything works fine, except that when I draw a polyline between two coordinates, and later try to remove it, the polyline doesn't get removed (at least not permanently). When I use the methods below to try to remove the old polyline, and add a new one I get two polylines:
_polyLine.clear()
_polyLine.remove("id")
polylines.removeWhere((m) => m.polylineId.value == 'polyId$_randPolyId')
It gets removed and then added again in addition to the new one. This results in the picture below:
...
void showPinsOnMap() {
// _polylines.removeWhere(
// (m) => m.polylineId.value == 'polyId$_randPolyId');
// _polylines.clear()
_polylines = {};
print("\n\n\nPolyLines Lenght: ${_polylines.length}\n\n\n");
var pinPosition = LatLng(_currentLocation.latitude,_currentLocation.longitude);
var destPosition = LatLng(_destinationLocation.latitude,
_destinationLocation.longitude);
_markers.add(Marker(
markerId: MarkerId('sourcePin'),
position: pinPosition,
icon: _sourceIcon
));
_markers.add(Marker(
markerId: MarkerId('destPin'),
position: destPosition,
icon: _destinationIcon,
));
setPolylines();
notifyListeners();
}
...
...
void setPolylines() async {
List<PointLatLng> result = await _polylinePoints.getRouteBetweenCoordinates(
_googleAPIKey,
_currentLocation.latitude,
_currentLocation.longitude,
_destinationLocation.latitude,
_destinationLocation.longitude).catchError((onError){
print("\n\n\n An Error Occured Possibly dure to network issues\n\n\n");
});
if(result != null){
print("Results not null");
if(result.isNotEmpty){
result.forEach((PointLatLng point){
_polylineCoordinates.add(
LatLng(point.latitude,point.longitude)
);
});
_isLoadingData = false;
_polylines.add(Polyline(
width: 5,
polylineId: PolylineId('polyId$_randPolyId'),
color:
Color.fromARGB(255, 40, 122, 198),
points: _polylineCoordinates
));
}
}
notifyListeners();
}
...
you need to clear polylineCoordinates before plotting new paths.
polylineCoordinates.clear(); // call this before checking result value.
polylineCoordinates.clear();
if(result != null){
print("Results not null");
if(result.isNotEmpty){
result.forEach((PointLatLng point){
_polylineCoordinates.add(
LatLng(point.latitude,point.longitude)
);
});
}
}
Related
Using flutter_polyline_points: ^1.0.0 & google_maps_flutter: ^2.2.1
So what I am trying to achieve is to draw polylines on Google Map at flutter following current WALKING user location [using Geolocator]. The code below works, except when I stay out of the road, polylines are not drawn after my location [the location of blue dot at google maps] but they stick to the main road and won't cross it's boundaries...
(https://i.stack.imgur.com/FHV2d.jpg)
CountDown func is counting down to 0 and then showing map/location/timer etc [start walk]
_CountDown() async {
const oneSec = Duration(seconds: 1);
_timer = Timer.periodic(oneSec, (timer) {
_startTimer == 0
? setState(
() {
timer.cancel();
_getCurrentLocation();
Future.delayed(const Duration(seconds: 5), () {
stopWatchTimer.onStartTimer();
_updateMapAndValues();
});
},
)
: setState(
() => _startTimer--,
);
});
}
_getCurrentLocation() is getting current position and sets late _currectPosition to later zoom on it with map.
_getCurrentLocation() async {
await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best,
forceAndroidLocationManager: true)
.then((Position position) async {
setState(() {
_currentPosition = position;
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: 18.0,
),
),
);
});
}).catchError((e) {
print(e);
});
}
After that I am stopping the timer/updating the map.
First I am getting current position to check if location changed, then I am creating polyline between old _currentposition and new position (later calc distance and coins but that's not that importand).
_updateMapAndValues() async {
bool petla = true;
while (petla) {
await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best,
forceAndroidLocationManager: true)
.then((Position position) async {
await Future.delayed(const Duration(milliseconds: 500));
if (_currentPosition.latitude != position.latitude &&
_currentPosition.longitude != position.longitude) {
_createPolylines(_currentPosition, position);
await _calculateDistance();
setState(() {
_currentPosition = position;
int result = distance * 1000 ~/ 50;
print('DYSTANS ILE COINOW : $result');
if (result > 0) {
while (coins < result) {
setState(
() => coins++,
);
}
}
});
}
});
}
}
The _createPolylines function. I thought it will work adding travelMode:walking but it does not. Still (mostly) following the roads and when I am moving at the edges (screen) it just draw straight line.
late PolylinePoints polylinePoints;
List<LatLng> polylineCoords = [];
Map<PolylineId, Polyline> polylines = {};
_createPolylines(Position start, Position end) async {
polylinePoints = PolylinePoints();
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
'AIzaSyDDyBb0N9_jthBS99PRJcT6CjFV2TI9J5E',
PointLatLng(start.latitude, start.longitude),
PointLatLng(end.latitude, end.longitude),
travelMode: TravelMode.walking,
avoidHighways: true,
);
if (result.points.isNotEmpty) {
result.points.forEach((element) {
polylineCoords.add(LatLng(element.latitude, element.longitude));
print('--------WYSWIETLAM: $polylineCoords');
});
}
PolylineId id = const PolylineId('poly');
Polyline polyline = Polyline(
polylineId: id,
color: Colors.red,
points: polylineCoords,
width: 5,
);
polylines[id] = polyline;
}
I want to display drivers' info above the markers on the map, like driver name and car name. but i do not know how to do so.
I am using flutter, flutter geofire and firebase realtime database
My code is
displayActiveDriversOnUserMap()
{ setState((){
markersSet.clear();
circleSet.clear();
Set<Marker> driversMarkerSet = Set<Marker>();
for(ActiverNearbyAvailableDrivers eachDriver in GeoFireAssistant.activeNearbyAvailableDriversList)
{
LatLng eachDriverActivePosition = LatLng(eachDriver.locationLatitude!, eachDriver.locationLongitude!);
Marker marker = Marker(
markerId: MarkerId(eachDriver.driverId!),
position: eachDriverActivePosition,
icon: activeNearByIcon!,
rotation: 360,
);
driversMarkerSet.add(marker);
}
setState ((){
markersSet = driversMarkerSet;
});
});
}
createActiveNearByDriverIconMarker()
{
if(activeNearByIcon == null)
{
ImageConfiguration imageConfiguration = createLocalImageConfiguration(context, size: const Size(2, 2));
BitmapDescriptor.fromAssetImage(imageConfiguration, "images/car.png").then((value)
{
activeNearByIcon = value;
});
}
}
}
screenshot of map
I want to use a custom marker as user position. I am listening to location event and on each move I want to set new lat/lon on this marker. However I don't see any options to update markers position. How can I achieve this? I've tried removing the current marker and adding a new one, but there's ugly flash effect which I do not want.
final marker = Marker(
markerId: MarkerId('1'),
position: LatLng(_latitude, _longitude),
icon: await customIcon()
);
setState(() {
_markers.add(marker);
});
_location.onLocationChanged.listen((event) async {
//here I want to update the marker lat lng with new event.latitude and event.longitude
});
Try the following
_location.onLocationChanged.listen((event) async {
final newMarker = Marker(
markerId: MarkerId('1'),
position: LatLng(event.latitude, event.longitude),
icon: await customIcon()
);
final oldMarkerIndex = _markers.indexWhere((marker) => marker.markerId == MarkerId('1'));
if(oldMarkerIndex >= 0) { // If it exists
setState(() {
_markers[oldMarkerIndex] = newMarker;
});
}
});
I am able to add the markers to the map but when I try to add the name of the place in the infowindow, only one name appears on all the infowindows. My intention is to have a different name for each infowindow.
Here's the code for the function
_handleTapOrig() {
LatLng tappedPoint;
setState(() {
FirebaseFirestore.instance.collection('bus_stages').get().then((value) {
if (value.docs.isNotEmpty) {
for (int i = 0; i < value.docs.length; i++) {
DocumentSnapshot snap = value.docs[i];
GeoPoint geoPoint = snap.get("location");
double mylat = geoPoint.latitude;
String jje = snap.get("stage_name");
double mylng = geoPoint.longitude;
LatLng mypoint = LatLng(mylat, mylng);
setState(() {
_mylatlng.add(LatLng(mylat, mylng)
);
});
///Add markers
myMarker = [];
_mylatlng.forEach((element) {
tappedPoint = element;
myMarker.add(Marker(
markerId: MarkerId(tappedPoint.toString()),
position: tappedPoint,
icon: myBitmapDescriptor,
/// BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueCyan),
infoWindow: InfoWindow(title: "Bus Stage ${snap.get("stage_name")}",
snippet: 'Tap Google directions button to navigate to stage'),
));
});
}
// print(_mylatlng);
}
});
// print('List of Markers: $myMarker');
});
}
I am using google_maps_flutter for creating a Google map with two types of markers. When one type of marker is dragged over the other, I want to remove the dragged marker and then perform a function. I am able to do this.
But, in case the dragged marker is dropped in a wrong position, then I want to place the marker back to its original position. I couldn't find any event or method to achieve this. How can this be done?
Here is my code for adding markers:
markers.add(
Marker(
markerId: packageMarkerId,
draggable: true,
icon: _unassignedOrderMarkerIcon,
onTap: () {
print('marker tapped');
},
position: LatLng(coordinates.latitude, coordinates.longitude),
onDragEnd: (LatLng latLng) {
double newLat =
double.parse(latLng.latitude.toStringAsFixed(1));
double newLong =
double.parse(latLng.longitude.toStringAsFixed(1));
for (var user in usersDocuments) {
Map<String, dynamic> userLocation =
user.data['user_location'];
if (userLocation != null) {
if (newLat == userLocation['latitude'] &&
newLong == userLocation['longitude']) {
print('Equal coords: $latLng');
markers.removeWhere((element) {
print('Marker removed!');
return element.markerId == packageMarkerId;
});
setState(() {
_markers = markers;
});
return;
} else {
print('Unequal coords, not merged!');
print(userLocation['latitude']);
print(userLocation['longitude']);
return;
}
}
}
},
),
);