Sitemap

🌍 Master Google Maps in Flutter: From Zero to Map Hero!

6 min readOct 16, 2025

--

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.

Press enter or click to view image in full size

1. Add Dependency

Open your pubspec.yaml and add:

dependencies:
flutter:
sdk: flutter
google_maps_flutter: ^2.3.0 # Check for latest version

Then run:

flutter pub get

2. Configure Android

  1. Open android/app/src/main/AndroidManifest.xml
  2. 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

  1. Open ios/Runner/AppDelegate.swift and 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 map
  • onMapCreated: Callback when the map is ready
  • initialCameraPosition: Sets the starting position and zoom
  • LatLng: 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 🌍

--

--