When i update the polyline code, on location change method, It gives me additional straight line. I want to update my polyline when user move from one source to destination. I am able to create a polyline route but i want that route become shorter with the location of the user. So i am replacing the source location with user's current location. And if user change takes different turn than the polyline should update as per it happens in google map apps.
below is the code.
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
import 'package:flutter/material.dart';
import 'package:routelines/components/map_pin_pill.dart';
import 'dart:async';
import 'package:routelines/models/pin_pill_info.dart';
const double CAMERA_ZOOM = 16;
const double CAMERA_TILT = 80;
const double CAMERA_BEARING = 30;
const LatLng SOURCE_LOCATION = LatLng(22.993966, 72.498510);
const LatLng DEST_LOCATION = LatLng(23.014672, 72.530558);
class DirectionPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => DirectionPageState();
}
class DirectionPageState extends State<DirectionPage> {
Completer<GoogleMapController> _controller = Completer();
Set<Marker> _markers = Set<Marker>();
Set<Polyline> _polylines = Set<Polyline>();
List<LatLng> polylineCoordinates = [];
PolylinePoints polylinePoints;
String googleAPIKey = "<YourKey>";
BitmapDescriptor sourceIcon;
BitmapDescriptor destinationIcon;
LocationData currentLocation;
LocationData destinationLocation;
Location location;
double pinPillPosition = -100;
int polyId = 1;
PinInformation currentlySelectedPin = PinInformation(
pinPath: '',
avatarPath: '',
location: LatLng(0, 0),
locationName: '',
labelColor: Colors.grey);
PinInformation sourcePinInfo;
PinInformation destinationPinInfo;
@override
void initState() {
super.initState();
location = new Location();
setInitialLocation();
polylinePoints = PolylinePoints();
location.onLocationChanged().listen((LocationData cLoc) {
currentLocation = cLoc;
updatePinOnMap();
setPolylines();
});
setSourceAndDestinationIcons();
}
@override
void dispose() {
super.dispose();
}
void setSourceAndDestinationIcons() async {
BitmapDescriptor.fromAssetImage(
ImageConfiguration(devicePixelRatio: 2.0), 'assets/driving_pin.png')
.then((onValue) {
sourceIcon = onValue;
});
BitmapDescriptor.fromAssetImage(ImageConfiguration(devicePixelRatio: 2.0),
'assets/destination_map_marker.png')
.then((onValue) {
destinationIcon = onValue;
});
}
void setInitialLocation() async {
currentLocation = await location.getLocation();
destinationLocation = LocationData.fromMap({
"latitude": DEST_LOCATION.latitude,
"longitude": DEST_LOCATION.longitude
});
}
@override
Widget build(BuildContext context) {
CameraPosition initialCameraPosition = CameraPosition(
zoom: CAMERA_ZOOM,
tilt: CAMERA_TILT,
bearing: CAMERA_BEARING,
target: SOURCE_LOCATION);
if (currentLocation != null) {
initialCameraPosition = CameraPosition(
target: LatLng(currentLocation.latitude, currentLocation.longitude),
zoom: CAMERA_ZOOM,
tilt: CAMERA_TILT,
bearing: CAMERA_BEARING);
}
return Scaffold(
body: Stack(
children: <Widget>[
GoogleMap(
myLocationEnabled: true,
compassEnabled: true,
tiltGesturesEnabled: false,
markers: _markers,
polylines: _polylines,
mapType: MapType.normal,
initialCameraPosition: initialCameraPosition,
onTap: (LatLng loc) {
},
onMapCreated: (GoogleMapController controller) {
controller.setMapStyle(Utils.mapStyles);
_controller.complete(controller);
print("map opened");
showPinsOnMap();
}),
MapPinPillComponent(
pinPillPosition: pinPillPosition,
currentlySelectedPin: currentlySelectedPin)
],
),
);
}
void showPinsOnMap() {
if (currentLocation != null && destinationLocation != null) {
var pinPosition =
LatLng(currentLocation.latitude, currentLocation.longitude);
// print("pinPosition >> $pinPosition");
var destPosition =
LatLng(destinationLocation.latitude, destinationLocation.longitude);
sourcePinInfo = PinInformation(
locationName: "Start Location",
location: SOURCE_LOCATION,
pinPath: "assets/driving_pin.png",
avatarPath: "assets/square_pin.png",
labelColor: Colors.blueAccent);
destinationPinInfo = PinInformation(
locationName: "End Location",
location: DEST_LOCATION,
pinPath: "assets/destination_map_marker.png",
avatarPath: "assets/square_pin.png",
labelColor: Colors.purple);
_markers.add(Marker(
markerId: MarkerId('sourcePin'),
position: pinPosition,
onTap: () {
setState(() {
currentlySelectedPin = sourcePinInfo;
pinPillPosition = 0;
});
},
icon: sourceIcon));
// destination pin
_markers.add(Marker(
markerId: MarkerId('destPin'),
position: destPosition,
onTap: () {
setState(() {
currentlySelectedPin = destinationPinInfo;
pinPillPosition = 0;
});
},
icon: destinationIcon));
setPolylines();
}
}
void setPolylines() async {
List<PointLatLng> result = await polylinePoints.getRouteBetweenCoordinates(
googleAPIKey,
currentLocation.latitude,
currentLocation.longitude,
destinationLocation.latitude,
destinationLocation.longitude);
if (result.isNotEmpty) {
result.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
final String polylineIdVal = 'polyline_id_$polyId';
polyId++;
final PolylineId polylineId = PolylineId(polylineIdVal);
_polylines = new Set<Polyline>();
setState(() {
_polylines.add( Polyline(
width: 6,
// set the width of the polylines
polylineId: polylineId,
geodesic: true,
consumeTapEvents: true,
color: Colors.blue,
points: polylineCoordinates));
});
}
}
void updatePinOnMap() async {
if (currentLocation != null && destinationLocation != null) {
var pinPosition =
LatLng(currentLocation.latitude, currentLocation.longitude);
// print("pinPosition >> $pinPosition");
var destPosition =
LatLng(destinationLocation.latitude, destinationLocation.longitude);
sourcePinInfo = PinInformation(
locationName: "Start Location",
location: SOURCE_LOCATION,
pinPath: "assets/driving_pin.png",
avatarPath: "assets/square_pin.png",
labelColor: Colors.blueAccent);
destinationPinInfo = PinInformation(
locationName: "End Location",
location: DEST_LOCATION,
pinPath: "assets/destination_map_marker.png",
avatarPath: "assets/square_pin.png",
labelColor: Colors.purple);
_markers.add(Marker(
markerId: MarkerId('sourcePin'),
position: pinPosition,
onTap: () {
setState(() {
currentlySelectedPin = sourcePinInfo;
pinPillPosition = 0;
});
},
icon: sourceIcon));
// destination pin
_markers.add(Marker(
markerId: MarkerId('destPin'),
position: destPosition,
onTap: () {
setState(() {
currentlySelectedPin = destinationPinInfo;
pinPillPosition = 0;
});
},
icon: destinationIcon));
CameraPosition cPosition = CameraPosition(
zoom: CAMERA_ZOOM,
tilt: CAMERA_TILT,
bearing: CAMERA_BEARING,
target: LatLng(currentLocation.latitude, currentLocation.longitude),
);
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(cPosition));
setState(() {
// print("pinPosition lat " + currentLocation.latitude.toString()+" long "+ currentLocation.longitude.toString());
var pinPosition =
LatLng(currentLocation.latitude, currentLocation.longitude);
sourcePinInfo.location = pinPosition;
_markers.removeWhere((m) => m.markerId.value == 'sourcePin');
_markers.add(Marker(
markerId: MarkerId('sourcePin'),
onTap: () {
setState(() {
currentlySelectedPin = sourcePinInfo;
pinPillPosition = 0;
});
},
position: pinPosition, // updated position
icon: sourceIcon));
});
}
}
}
Any help would be appreciated!
Solved the issue by clear the polylineCoordinates before adding the polyline.