I was working with the integration of google maps in a flutter application. I have added multiple markers in the app. Also, I have added directions between two markers using flutter_polyline_points. The problem is how can I put a widget over the polyline points to show the distance or estimated time to travel which I have calculated using Distance metrics API.
Google maps
child: GoogleMap(
mapType: MapType.normal,
markers: Set<Marker>.of(markerData.values),
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 15.0,
),
// zoomControlsEnabled: false,
mapToolbarEnabled: true,
myLocationButtonEnabled: true,
myLocationEnabled: true,
polylines: Set<Polyline>.of(polylines.values),
),
Markers
void initMarkers(markerDetails, markerId) async {
final markerIdVal = markerId;
final MarkerId markerIdData = MarkerId(markerIdVal);
final Marker marker = Marker(
markerId: markerIdData,
position: LatLng(markerDetails["latitude"], markerDetails["longitude"]),
icon: await BitmapDescriptor.fromAssetImage(
ImageConfiguration(devicePixelRatio: 2.5),
'assets/images/marker.png'),
infoWindow:
InfoWindow(title: markerDetails["title"], snippet: distanceToLocation),
onTap: () {
_handleMarkerTap(
LatLng(markerDetails["latitude"], markerDetails["longitude"]));
});
setState(() {
markerData[markerIdData] = marker;
});
}
Polyline points
//Get polyline
void _getPolyline(latitude, longitude) async {
List<LatLng> polylineCoordinates = [];
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
"MY_API_KEY",
PointLatLng(13.0323, 77.57),
PointLatLng(latitude, longitude),
travelMode: TravelMode.walking,
);
if (result.points.isNotEmpty) {
result.points.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
} else {
print(result.errorMessage);
}
_addPolyLine(polylineCoordinates);
}
//Add polylines to the map
_addPolyLine(List<LatLng> polylineCoordinates) {
PolylineId id = PolylineId("poly");
Polyline polyline = Polyline(
polylineId: id,
color: Colors.deepOrange,
points: polylineCoordinates,
width: 3,
patterns: [PatternItem.dash(15), PatternItem.gap(10)],
);
polylines[id] = polyline;
}
Related
I have added a google map to my flutter application,
But when I use a flutter_polyline_points to show the road nothing is gone to show
I haven see any tutorial to fix this problem but then I knew that to
Decode an encoded google polyline string e.g _piFps|U_ulLnnqC_mqNvxq`#
How to get the google polyline string to use in my app
that is my code
_addPolyLine() {
PolylineId id = PolylineId("poly");
Polyline polyline = Polyline(
polylineId: id, color: Colors.red, points: polylineCoordinates);
polylines[id] = polyline;
setState(() {});
}
_getPolyline() async {
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
googleAPiKey,
PointLatLng(36.3416751898107, 43.6087730170814),
PointLatLng(36.18702370508709, 43.979696040252136),
travelMode: TravelMode.driving,
);
if (result.points.isNotEmpty) {
result.points.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
}
_addPolyLine();
}
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(_originLatitude, _originLongitude), zoom: 15),
myLocationEnabled: true,
tiltGesturesEnabled: true,
compassEnabled: true,
scrollGesturesEnabled: true,
zoomGesturesEnabled: true,
onMapCreated: _onMapCreated,
markers: Set<Marker>.of(markers.values),
polylines: Set<Polyline>.of(polylines.values),
),
the polyline is following the Route but it's not accurate only in long distances
this is short distance vs a long one
CLick here to see the image
i am using google_polyline_algorithm package to decode the response
i think the problem is in the request parameters
my code:
Dio dio = Dio();
List<LatLng> polyLineCoordinates = [];
final response = await dio.get(
"https://maps.googleapis.com/maps/api/directions/json?",
queryParameters: {
'origin':
'${myLocation.target.latitude},${myLocation.target.longitude}',
'destination':
'${orderLocation.target.latitude},${orderLocation.target.longitude}',
'key': "Google API Key",
'alternatives': 'false',
'travelMode':'DRIVE',
'optimizeWaypointOrder': false,
'polylineQuality': 'HIGH_QUALITY',
},
);
final lines = decodePolyline(
response.data["routes"][0]['overview_polyline']['points']);
lines.forEach((point) {
polyLineCoordinates
.add(LatLng(point[0].toDouble(), point[1].toDouble()));
});
widget code:
GoogleMap(
markers: {
Marker(
markerId: MarkerId('My Location'),
position: mapProvider.orderLocation.target,
icon: BitmapDescriptor.defaultMarker,
),
Marker(
markerId: MarkerId('Order Location'),
position: mapProvider.myLocation.target,
icon: BitmapDescriptor.defaultMarker,
),
Marker(
markerId: MarkerId('current Marker'),
position: mapProvider.currentLocaiton.target,
icon: BitmapDescriptor.defaultMarker,
)
},
polylines: {
Polyline(
// patterns: [
// PatternItem.
// ],
visible: true,
jointType: JointType.round,
geodesic: true,
endCap: Cap.roundCap,
startCap: Cap.roundCap,
polylineId: PolylineId("route"),
points: mapProvider.polyLineCoordinates,
color: Colors.blue
)
},
cameraTargetBounds: mapProvider.bounds!,
mapType: MapType.normal,
initialCameraPosition: mapProvider.orderLocation,
minMaxZoomPreference: MinMaxZoomPreference(10, 16),
onMapCreated: mapProvider.getCurrentLocation,
)
info:
Flutter version 3.0.1
google_maps_flutter: ^2.2.0
dio: ^4.0.6
google_polyline_algorithm: ^3.1.0
In Flutter, I created an array to add markers.
final List<Marker> _markers = <Marker>[];
Then I iterate all values and add them to this array
UserService().getAll().then((value) {
setState(() {
for (var element in value) {
_markers.add(Marker(
markerId: MarkerId(element.id.toString()),
position: LatLng((element.latitude), element.longitude),
infoWindow: InfoWindow(
title: element.name,
),
icon: BitmapDescriptor.defaultMarker,
));
}
});
}).catchError((e) {
debugPrint(e);
});
Finally on Google Maps i add this array to markers
final map = GoogleMap(
myLocationEnabled: true,
zoomControlsEnabled: false,
onMapCreated: _onMapCreated,
markers: _markers.map((e) => e).toSet(),
initialCameraPosition: CameraPosition(
target: _center,
zoom: 8.0,
),
);
The problem: Map only shows the first element of this array in the map. Does anybody know what´s wrong?
I have a compass plugin that is giving direction angle, and also location plugin that provide the current location. With these plugins, I use google maps placed under Streambuilder to put my current location as marker and with a line to another location.
The issue I am facing currently is how to rotate the map automatically when the device is rotated, as the first plugin provides direction angle (double value) that gets updated streams as the device rotate.
I wanted to use this angle value to update Google Maps bearing automatically, so that the map rotates accordingly.
I have tired many ways but of no use. Google maps does not respond.
this is my code:
Completer<GoogleMapController> _controller = Completer();
return StreamBuilder(
stream: FlutterQiblah.qiblahStream,
builder: (_, AsyncSnapshot<QiblahDirection> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) return LoadingIndicator();
final qiblahDirection = snapshot.data;
_goToTheLake(qiblahDirection);
return GoogleMap(
mapType: MapType.satellite,
zoomGesturesEnabled: true,
compassEnabled: true,
myLocationEnabled: false,
myLocationButtonEnabled: true,
rotateGesturesEnabled: true,
initialCameraPosition: CameraPosition(
target: position,
zoom: 18,
// bearing: qiblahDirection.direction,
),
markers: Set<Marker>.of(
<Marker>[
widget.meccaMarker,
Marker(
draggable: true,
markerId: MarkerId('Marker'),
position: position,
icon: BitmapDescriptor.defaultMarker,
rotation: qiblahDirection.qiblah,
onTap: () {
_goToTheLake(qiblahDirection);
},
onDragEnd: (LatLng value) {
position = value;
_positionStream.sink.add(value);
},
zIndex: 5,
),
],
),
circles: Set<Circle>.of([
Circle(
circleId: CircleId("Circle"),
radius: 10,
center: position,
fillColor: Theme.of(context).primaryColorLight.withAlpha(100),
strokeWidth: 1,
strokeColor: Theme.of(context).primaryColorDark.withAlpha(100),
zIndex: 3,
)
]),
polylines: Set<Polyline>.of([
Polyline(
polylineId: PolylineId("Line"),
points: [position, QiblahMaps.LatLong],
color: Theme.of(context).primaryColor,
width: 5,
zIndex: 4,
)
]),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
);
},
)
I have placed this function as future called from inside stream builder in order to change the "bearing" of the map:
final GoogleMapController controller = await _controller.future;
controller.moveCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
bearing: qiblahDirection.direction,
),
),
);
} ```
Try this plugin flutter_compass
use the events to update google map bearing as you wish
I want to draw Polyline from my current location to another dynamic location. But
sometimes it's being draw but sometimes throwing exception when I search places with flutter_google_places plugin.
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'PlaceDetails'
here Some piece of my code:
Api:
const kGoogleApiKey = "AIz#######_###############";
GoogleMapsPlaces _places = GoogleMapsPlaces(apiKey: kGoogleApiKey);
Here I Declared a list type variable with LatLng type:
List<LatLng> latlng = [];
current Location:
// I called this method from initState() method
void getCurrentLocation()async{
Position pos= await Geolocator().getCurrentPosition();
setState(() {
position = pos;
print("CurrentLatLng__= ${position.latitude + position.longitude }");
latlng.add(LatLng(position.latitude,position.longitude)); // Adding current location to the list
});
}
Google Map:
body: GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(position.latitude,position.longitude),
zoom: 14.4746,
),
compassEnabled: true,
myLocationEnabled: true,
// myLocationButtonEnabled: true,
mapType: MapType.normal,
onMapCreated: (GoogleMapController controller){
_controller.complete(controller);
},
markers: isSelectedDropff
?{ Marker(
markerId: MarkerId(globalPlaceIdDropOff),
infoWindow: InfoWindow(
title: placeNameDropOff,
// snippet: "${responseResult.types?.first}"
),
icon: BitmapDescriptor.defaultMarker,
position: LatLng(dropOffLat , dropOffLng ),
),
}:
{
Marker(
markerId: MarkerId("current loc"),
infoWindow: InfoWindow(
title: "Current",
// snippet: "${responseResult.types?.first}"
),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
position: LatLng(position.latitude, position.longitude),
),
},
polylines: isSelectedDropOff ?{
Polyline(
polylineId: PolylineId("One") ,
points:latlng,
color: Colors.red,
visible: true
)
}
:null,
),
Autocompleter:
onTap: ()async{
// show input autocomplete with selected mode
// then get the Prediction selected
Prediction p =await PlacesAutocomplete.show(
context: context,
apiKey: kGoogleApiKey,
mode: Mode.overlay, // Mode.fullscreen
language: "fr",
components: [new Component(Component.country, "fr")]
);
displayPredictionDropOff(p);
},
// called it from TextField widget with it's constructor onTap:
Future<Null> displayPredictionDropOff(Prediction p) async {
if (p != null) {
PlacesDetailsResponse detail =
await _places.getDetailsByPlaceId(p.placeId); //Note: exception occurring at this line
var placeId = p.placeId;
double lat = detail.result.geometry.location.lat;
double lng = detail.result.geometry.location.lng;
var address = await Geocoder.local.findAddressesFromQuery(p.description);
setState(() {
placeNameDropOff = detail.result.name;
dropOffLat = lat;
dropOffLng = lng;
globalPlaceIdDropOff = placeId;
isSelectedDropOff = true;
latlng.add(LatLng(lat,lng)); // add second location to the list
});
print("lat------$lat");
print("lng--------$lng");
print("description-----${p.description}");
print("name------${detail.result.name}");
print("address----------$address");
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(lat, lng),
zoom: 19.151926040649414
),
));
}
}
Note: exception (Unhandled Exception: type 'List' is not a subtype of type 'PlaceDetails') occurring at below line
PlacesDetailsResponse detail =
await _places.getDetailsByPlaceId(p.placeId);