🌍 Master Google Maps in Flutter: From Zero to Map Hero!
Google Maps is a powerful tool for building location-based apps. In Flutter, you can integrate Google Maps using the google_maps_flutter package. This guide will take you step-by-step from setup to advanced usage.
1. Add Dependency
Open your pubspec.yaml and add:
dependencies:
flutter:
sdk: flutter
google_maps_flutter: ^2.3.0 # Check for latest versionThen run:
flutter pub get2. Configure Android
- Open
android/app/src/main/AndroidManifest.xml - Add the following inside the
<application>tag:
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_GOOGLE_MAP_API_KEY"/>3. Configure iOS
- Open
ios/Runner/AppDelegate.swiftand add:
import GoogleMaps
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("YOUR_GOOGLE_MAP_API_KEY")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}4. Basic Usage
Create a simple map widget:
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapScreen extends StatefulWidget {
@override
_MapScreenState createState() => _MapScreenState();
}
class _MapScreenState extends State<MapScreen> {
late GoogleMapController mapController;
final LatLng _center = const LatLng(81.42796133580664, 72.085749655962);
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Google Maps in Flutter')),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 14.0,
),
),
);
}
}Explanation:
GoogleMap: Widget to display the maponMapCreated: Callback when the map is readyinitialCameraPosition: Sets the starting position and zoomLatLng: Represents latitude and longitude
5. Adding Markers
Set<Marker> _markers = {};
@override
void initState() {
super.initState();
_markers.add(
Marker(
markerId: MarkerId('1'),
position: _center,
infoWindow: InfoWindow(
title: 'My Location',
snippet: 'This is where I am!',
),
),
);
}Add markers to the map:
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 14.0,
),
markers: _markers,
)You can create custom markers from any Flutter widget using the widget_to_marker package.
Future<void> _addCustomMarker() async {
// Convert a Flutter widget to BitmapDescriptor
final customIcon = await const CustomMarkerWidget().toBitmapDescriptor(
logicalSize: const Size(150, 150),
imageSize: const Size(150, 150),
);
final marker = Marker(
markerId: const MarkerId("1"),
position: const LatLng(18.996, 72.828),
draggable: true,
alpha: 0.9,
infoWindow: const InfoWindow(
title: "Hello James",
snippet: "Hey Whatsapp",
),
icon: customIcon, // Set the custom icon
);
setState(() {
_markers.add(marker);
});
}Explanation:
- widget_to_marker: Converts any Flutter widget into a marker icon
- logicalSize & imageSize: Controls the size of the marker
- draggable: Allows the user to move the marker on the map
- alpha: Sets transparency
- infoWindow: Popup when the marker is tapped
Get Rugved Apraj’s stories in your inbox
Join Medium for free to get updates from this writer.
6. Moving the Camera
mapController.animateCamera(
CameraUpdate.newLatLng(LatLng(18.43296265331129, 72.08832357078792)),
);7. Adding Polylines & Polygons
Polyline Example:
Set<Polyline> _polylines = {
Polyline(
polylineId: PolylineId('line1'),
points: [
LatLng(18.42796133580664, 72.085749655962),
LatLng(18.43296265331129, 72.08832357078792),
],
color: Colors.blue,
width: 5,
),
};Polygon Example:
Set<Polygon> _polygons = {
Polygon(
polygonId: PolygonId('polygon1'),
points: [
LatLng(37.42796133580664, -122.085749655962),
LatLng(37.430, -122.09),
LatLng(37.435, -122.082),
],
fillColor: Colors.green.withOpacity(0.3),
strokeColor: Colors.green,
strokeWidth: 2,
),
};Add them to the map:
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 14.0,
),
markers: _markers,
polylines: _polylines,
polygons: _polygons,
)8. Map Gestures & Controls
GoogleMap(
zoomGesturesEnabled: true,
scrollGesturesEnabled: true,
rotateGesturesEnabled: true,
tiltGesturesEnabled: true,
zoomControlsEnabled: true,
compassEnabled: true,
buildingsEnabled: true,
trafficEnabled: true,
mapType: MapType.hybrid,
minMaxZoomPreference: MinMaxZoomPreference(0, 100),
)9. Handling Map Taps
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(target: _center, zoom: 14.0),
onTap: (LatLng position) {
print('Tapped position: $position');
setState(() {
_markers.add(
Marker(
markerId: MarkerId(position.toString()),
position: position,
),
);
});
},
)10. Custom Map Styling
If you want custom map styling (like changing colors of roads, water, parks, etc.), then yes, you do need a JSON file.
- You can get it from Google Maps Styling Wizard — it generates a JSON for you.
- Copy the JSON and paste in the _mapStyle variable.
import 'package:flutter/services.dart';
String styleJson = '[
{
"elementType": "geometry",
"stylers": [
{
"color": "#212121"
}
]
},
{
"elementType": "labels.icon",
"stylers": [
{
"visibility": "off"
}
]
},
{
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"elementType": "labels.text.stroke",
"stylers": [
{
"color": "#212121"
}
]
},
{
"featureType": "administrative",
"elementType": "geometry",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "administrative.country",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#9e9e9e"
}
]
},
{
"featureType": "administrative.land_parcel",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "administrative.locality",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#bdbdbd"
}
]
},
{
"featureType": "poi",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "poi.park",
"elementType": "geometry",
"stylers": [
{
"color": "#181818"
}
]
},
{
"featureType": "poi.park",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"featureType": "poi.park",
"elementType": "labels.text.stroke",
"stylers": [
{
"color": "#1b1b1b"
}
]
},
{
"featureType": "road",
"elementType": "geometry.fill",
"stylers": [
{
"color": "#2c2c2c"
}
]
},
{
"featureType": "road",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#8a8a8a"
}
]
},
{
"featureType": "road.arterial",
"elementType": "geometry",
"stylers": [
{
"color": "#373737"
}
]
},
{
"featureType": "road.highway",
"elementType": "geometry",
"stylers": [
{
"color": "#3c3c3c"
}
]
},
{
"featureType": "road.highway.controlled_access",
"elementType": "geometry",
"stylers": [
{
"color": "#4e4e4e"
}
]
},
{
"featureType": "road.local",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"featureType": "transit",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "water",
"elementType": "geometry",
"stylers": [
{
"color": "#000000"
}
]
},
{
"featureType": "water",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#3d3d3d"
}
]
}
]';
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(target: _center, zoom: 14.0),
style: jsonEncode(styleJson),
)11. Creating Heatmap
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(target: _center, zoom: 14.0),
style: jsonEncode(styleJson),
heatmaps: {
Heatmap(
heatmapId: HeatmapId("1"),
data: [
WeightedLatLng(LatLng(18.0, 72.0), weight: 1),
WeightedLatLng(LatLng(18.0, 72.0), weight: 5),
WeightedLatLng(LatLng(18.0, 72.0), weight: 15),
],
radius: HeatmapRadius.fromPixels(75),
gradient: HeatmapGradient(
[
HeatmapGradientColor(Colors.green, 0.2),
HeatmapGradientColor(Colors.red, 1),
],
),
),
}
)WeightedLatLng: Each point on the map with a weight that determines intensity.radius: How “spread out” the heat is around each point.gradient: Defines colors for low-to-high intensity (e.g., green → red).
12. Circles
circles: {
Circle(
circleId: CircleId("circle1"),
center: LatLng(18.427961, 72.085749),
radius: 300, // in meters
fillColor: Colors.blue.withOpacity(0.3),
strokeColor: Colors.blue,
strokeWidth: 2,
),
}Explanation:
- Highlight regions or zones on the map
- radius is in meters
- fillColor with opacity gives a translucent area
13. Full Example Code
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapScreen extends StatefulWidget {
@override
_MapScreenState createState() => _MapScreenState();
}
class _MapScreenState extends State<MapScreen> {
late GoogleMapController mapController;
final LatLng _center = const LatLng(18.42796133580664, 72.085749655962);
Set<Marker> _markers = {};
Set<Polyline> _polylines = {
Polyline(
polylineId: PolylineId('line1'),
points: [
LatLng(18.42796133580664, 72.085749655962),
LatLng(18.43296265331129, 72.08832357078792),
],
color: Colors.blue,
width: 5,
),
};
Set<Polygon> _polygons = {
Polygon(
polygonId: PolygonId('polygon1'),
points: [
LatLng(37.42796133580664, -122.085749655962),
LatLng(37.430, -122.09),
LatLng(37.435, -122.082),
],
fillColor: Colors.green.withOpacity(0.3),
strokeColor: Colors.green,
strokeWidth: 2,
),
};
String styleJson = "[
{
"elementType": "geometry",
"stylers": [
{
"color": "#212121"
}
]
},
{
"elementType": "labels.icon",
"stylers": [
{
"visibility": "off"
}
]
},
{
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"elementType": "labels.text.stroke",
"stylers": [
{
"color": "#212121"
}
]
},
{
"featureType": "administrative",
"elementType": "geometry",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "administrative.country",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#9e9e9e"
}
]
},
{
"featureType": "administrative.land_parcel",
"stylers": [
{
"visibility": "off"
}
]
},
{
"featureType": "administrative.locality",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#bdbdbd"
}
]
},
{
"featureType": "poi",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "poi.park",
"elementType": "geometry",
"stylers": [
{
"color": "#181818"
}
]
},
{
"featureType": "poi.park",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"featureType": "poi.park",
"elementType": "labels.text.stroke",
"stylers": [
{
"color": "#1b1b1b"
}
]
},
{
"featureType": "road",
"elementType": "geometry.fill",
"stylers": [
{
"color": "#2c2c2c"
}
]
},
{
"featureType": "road",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#8a8a8a"
}
]
},
{
"featureType": "road.arterial",
"elementType": "geometry",
"stylers": [
{
"color": "#373737"
}
]
},
{
"featureType": "road.highway",
"elementType": "geometry",
"stylers": [
{
"color": "#3c3c3c"
}
]
},
{
"featureType": "road.highway.controlled_access",
"elementType": "geometry",
"stylers": [
{
"color": "#4e4e4e"
}
]
},
{
"featureType": "road.local",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#616161"
}
]
},
{
"featureType": "transit",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#757575"
}
]
},
{
"featureType": "water",
"elementType": "geometry",
"stylers": [
{
"color": "#000000"
}
]
},
{
"featureType": "water",
"elementType": "labels.text.fill",
"stylers": [
{
"color": "#3d3d3d"
}
]
}
]";
@override
void initState() {
super.initState();
_markers.add(
Marker(
markerId: MarkerId('1'),
position: _center,
infoWindow: InfoWindow(
title: 'My Location',
snippet: 'This is where I am!',
),
),
);
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Google Maps in Flutter')),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 14.0,
),
style: jsonEncode(styleJson),
markers: _markers,
zoomControlsEnabled: true,
zoomGesturesEnabled: true,
scrollGesturesEnabled: true,
myLocationEnabled: true,
myLocationButtonEnabled: true,
compassEnabled: true,
buildingsEnabled: true,
onTap: (position) {
setState(() {
_markers.add(
Marker(
markerId: MarkerId(position.toString()),
position: position,
),
);
});
},
heatmaps: {
Heatmap(
heatmapId: HeatmapId("1"),
data: [
WeightedLatLng(LatLng(18.0, 72.0), weight: 1),
WeightedLatLng(LatLng(18.0, 72.0), weight: 5),
WeightedLatLng(LatLng(18.0, 72.0), weight: 15),
],
radius: HeatmapRadius.fromPixels(75),
gradient: HeatmapGradient(
[
HeatmapGradientColor(Colors.green, 0.2),
HeatmapGradientColor(Colors.red, 1),
],
),
),
},
polylines: _polylines,
polygons: _polygons,
circles: {
Circle(
circleId: CircleId("circle1"),
center: LatLng(18.427961, 72.085749),
radius: 300, // in meters
fillColor: Colors.blue.withOpacity(0.3),
strokeColor: Colors.blue,
strokeWidth: 2,
),
}
),
);
}
}✍️ Author’s Note
If you found this guide helpful, give it a 👏 on Medium and share it with other Flutter developers! Start building location-based apps like a pro 🌍









