Recently, I was working on a flutter project which requires maps and route lines showing the path between two coordinates (the source and destination coordinates).
In this tutorial, I will show you how I was able to achieve this using this two packages from pub.dev
After installing this packages, we need to create a google project and get a Google Maps API key from the Google Developer Console.
You can also check this article on how to get an api key.
We also need to activate the following services on the developer console for our Google project:
- Maps SDK for Android
- Maps SDK for iOS
- Directions API
This can be done by clicking on the search icon on the app bar of the developer console and searching for this services then activating them
Lastly, we need to setup billing for our project, the Directions API which does the route generation requires billing to work. Though you won't be charged without activating auto charge after your free trial.
You can read this article on How to Setup Billing For Your Google Developer Account
We now need to setup Google maps for our flutter project.
On Android
Specify your API key in the application manifest android/app/src/main/AndroidManifest.xml
:
<manifest ...
<application ...
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="YOUR KEY HERE"/>
On iOS
Specify your API key in the application delegate ios/Runner/AppDelegate.m
:
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import "GoogleMaps/GoogleMaps.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GMSServices provideAPIKey:@"YOUR KEY HERE"];
[GeneratedPluginRegistrant registerWithRegistry:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
Or in your swift code, specify your API key in the application delegate ios/Runner/AppDelegate.swift
:
import UIKit
import Flutter
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("YOUR KEY HERE")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Adding Google Maps to Our Flutter Application
import 'dart:async';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
// Starting point latitude
double _originLatitude = 6.5212402;
// Starting point longitude
double _originLongitude = 3.3679965;
// Destination latitude
double _destLatitude = 6.849660;
// Destination Longitude
double _destLongitude = 3.648190;
// Markers to show points on the map
Map<MarkerId, Marker> markers = {};
class _MyAppState extends State<MyApp> {
// Google Maps controller
Completer<GoogleMapController> _controller = Completer();
// Configure map position and zoom
static final CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(_originLatitude, _originLongitude),
zoom: 9.4746,
);
@override
void initState() {
/// add origin marker origin marker
_addMarker(
LatLng(_originLatitude, _originLongitude),
"origin",
BitmapDescriptor.defaultMarker,
);
// Add destination marker
_addMarker(
LatLng(_originLatitude, _originLongitude),
"destination",
BitmapDescriptor.defaultMarkerWithHue(90),
);
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
myLocationEnabled: true,
tiltGesturesEnabled: true,
compassEnabled: true,
scrollGesturesEnabled: true,
zoomGesturesEnabled: true,
markers: Set<Marker>.of(markers.values),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
),
);
}
// This method will add markers to the map based on the LatLng position
_addMarker(LatLng position, String id, BitmapDescriptor descriptor) {
MarkerId markerId = MarkerId(id);
Marker marker =
Marker(markerId: markerId, icon: descriptor, position: position);
markers[markerId] = marker;
}
}
This should render google maps with two markers at the origin and destination coordinates.
Adding Polylines Between the Locations on Our Map
Now all we need to do is add the polylines to show the path between our point. To do this we make use of the flutter_polyline_points
package
Add ```dart
import 'package:flutter_polyline_points/flutter_polyline_points.dart';{% raw %}
``
to the imports at the top of the file.
Next, we need to define a variable to store the polylines we will later query for, and create a PolylinePoints object too.
Add this among other class properties we defined earlier
`dart
PolylinePoints polylinePoints = PolylinePoints();
Map<PolylineId, Polyline> polylines = {};
`
Next, we need to write a method to help us query the directions API for the points of the polyline
`dart
void _getPolyline() async {
List polylineCoordinates = [];
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
Constants.API_KEY,
PointLatLng(_originLatitude, _originLongitude),
PointLatLng(_destLatitude, _destLongitude),
travelMode: TravelMode.driving,
);
if (result.points.isNotEmpty) {
result.points.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
} else {
print(result.errorMessage);
}
_addPolyLine(polylineCoordinates);
}
`
We referenced a _addPolyLine
function from the _getPolyline
function, the _addPolyLine
will help us populate the maps with the polyline points. Let's create this method too
`dart
_addPolyLine(List<LatLng> polylineCoordinates) {
PolylineId id = PolylineId("poly");
Polyline polyline = Polyline(
polylineId: id,
color: Constants.primaryColorSwatch,
points: polylineCoordinates,
width: 8,
);
polylines[id] = polyline;
setState(() {});
}
`
Then we add the polylines
object to our GoogleMap
property
`dart
polylines: Set<Polyline>.of(polylines.values),
`
This is the final code
`dart
import 'dart:async';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
// Starting point latitude
double _originLatitude = 6.5212402;
// Starting point longitude
double _originLongitude = 3.3679965;
// Destination latitude
double _destLatitude = 6.849660;
// Destination Longitude
double _destLongitude = 3.648190;
// Markers to show points on the map
Map markers = {};
PolylinePoints polylinePoints = PolylinePoints();
Map polylines = {};
class _MyAppState extends State {
// Google Maps controller
Completer _controller = Completer();
// Configure map position and zoom
static final CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(_originLatitude, _originLongitude),
zoom: 9.4746,
);
@override
void initState() {
/// add origin marker origin marker
_addMarker(
LatLng(_originLatitude, _originLongitude),
"origin",
BitmapDescriptor.defaultMarker,
);
// Add destination marker
_addMarker(
LatLng(_destLatitude, _destLongitude),
"destination",
BitmapDescriptor.defaultMarkerWithHue(90),
);
_getPolyline();
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
myLocationEnabled: true,
tiltGesturesEnabled: true,
compassEnabled: true,
scrollGesturesEnabled: true,
zoomGesturesEnabled: true,
polylines: Set.of(polylines.values),
markers: Set.of(markers.values),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
),
);
}
// This method will add markers to the map based on the LatLng position
_addMarker(LatLng position, String id, BitmapDescriptor descriptor) {
MarkerId markerId = MarkerId(id);
Marker marker =
Marker(markerId: markerId, icon: descriptor, position: position);
markers[markerId] = marker;
}
_addPolyLine(List polylineCoordinates) {
PolylineId id = PolylineId("poly");
Polyline polyline = Polyline(
polylineId: id,
points: polylineCoordinates,
width: 8,
);
polylines[id] = polyline;
setState(() {});
}
void _getPolyline() async {
List polylineCoordinates = [];
PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
"YOUR API KEY HERE",
PointLatLng(_originLatitude, _originLongitude),
PointLatLng(_destLatitude, _destLongitude),
travelMode: TravelMode.driving,
);
if (result.points.isNotEmpty) {
result.points.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
} else {
print(result.errorMessage);
}
_addPolyLine(polylineCoordinates);
}
}
`
This is a link to a gist with complete code
Top comments (0)