Flutter, Google’s UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase, offers robust support for integrating maps. The google_maps_flutter
package is a popular choice for displaying Google Maps in your Flutter apps. This guide covers how to use the google_maps_flutter
package to display maps, add markers, and customize the map’s appearance.
Introduction to the google_maps_flutter
Package
The google_maps_flutter
package is a Flutter plugin that displays Google Maps. It provides a comprehensive set of features to interact with maps, including adding markers, polylines, polygons, and circles, as well as controlling camera movements and handling map events.
Why Use google_maps_flutter
?
- Integration: Seamlessly integrates Google Maps into Flutter apps.
- Customization: Offers extensive customization options for map appearance.
- Markers: Simplifies the process of adding and managing map markers.
- Map Controls: Provides methods to control camera position, zoom level, and more.
Setting Up Your Flutter Project
Before diving into the code, you’ll need to set up your Flutter project and configure it to use the google_maps_flutter
package.
Step 1: Add the Dependency
Add the google_maps_flutter
package to your pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
google_maps_flutter: ^2.5.0 # Use the latest version
Run flutter pub get
in your terminal to install the package.
Step 2: Configure Your API Keys
To use the google_maps_flutter
package, you need to obtain an API key from the Google Cloud Platform and configure it in your app. Here’s how to do it:
Android
- Open your
android/app/src/main/AndroidManifest.xml
file. - Add the following
<meta-data>
tag inside the<application>
tag:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package.name">
<application
android:label="Your App"
android:icon="@mipmap/ic_launcher">
<!-- You will need to get a maps_api_key for Google Maps -->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY" />
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Replace "YOUR_API_KEY"
with your actual API key.
iOS
- Open your
ios/Runner/AppDelegate.swift
file. - Add the following code at the top of the
application
method:
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_API_KEY")
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Replace "YOUR_API_KEY"
with your actual API key.
Displaying a Basic Map
Now that you’ve set up your project, you can start displaying a basic map in your Flutter app.
Step 1: Create a Map Widget
Create a stateful widget to hold the map and its state:
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(45.521563, -122.677433);
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Maps in Flutter'),
),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
),
);
}
}
In this code:
MapScreen
is a stateful widget that holds the map.GoogleMapController
is used to control the map._center
is the initial latitude and longitude of the map’s center._onMapCreated
is a callback function that’s called when the map is created. It provides aGoogleMapController
instance, which you can use to interact with the map.GoogleMap
is the widget that displays the map. It takes aninitialCameraPosition
property to set the starting position of the map.
Step 2: Add Markers to the Map
To add markers to the map, you’ll need to create a Set<Marker>
and pass it to the markers
property of the GoogleMap
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(45.521563, -122.677433);
final Set<Marker> _markers = {};
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
setState(() {
_markers.add(
Marker(
markerId: MarkerId(_center.toString()),
position: _center,
infoWindow: const InfoWindow(
title: 'My Location',
snippet: 'This is my current location',
),
icon: BitmapDescriptor.defaultMarker,
),
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Maps in Flutter'),
),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
markers: _markers,
),
);
}
}
In this code:
_markers
is aSet<Marker>
that holds the map markers.- Inside the
_onMapCreated
method, aMarker
is created and added to the_markers
set. - The
Marker
constructor takes several properties, includingmarkerId
,position
,infoWindow
, andicon
. - The
markers
property of theGoogleMap
widget is set to the_markers
set.
Customizing the Map
The google_maps_flutter
package allows you to customize the appearance of the map by setting various properties of the GoogleMap
widget.
Controlling Camera Movement
You can control the camera movement programmatically using the GoogleMapController
. For example, you can animate the camera to a new position:
void _goToNewLocation() {
final LatLng newLocation = const LatLng(45.521563, -122.0); // New location
mapController.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
target: newLocation,
zoom: 12,
tilt: 50.0,
bearing: 45.0,
),
));
}
Call this method in response to a user action, such as pressing a button:
FloatingActionButton(
onPressed: _goToNewLocation,
child: const Icon(Icons.map),
)
Changing Map Type
You can change the map type by setting the mapType
property of the GoogleMap
widget. Available map types include MapType.normal
, MapType.satellite
, MapType.hybrid
, and MapType.terrain
.
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
mapType: MapType.hybrid, // Set the map type to hybrid
markers: _markers,
)
Enabling Traffic Data
To display traffic data on the map, set the trafficEnabled
property to true
:
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
trafficEnabled: true, // Enable traffic data
markers: _markers,
)
Customizing Markers
You can customize the appearance of markers by using custom icons and info windows.
Custom Icons
Load a custom image as a marker icon:
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
Future<BitmapDescriptor> _bitmapDescriptorFromAsset(String assetName, int width) async {
final ByteData data = await rootBundle.load(assetName);
final ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);
final ui.FrameInfo fi = await codec.getNextFrame();
final byteData = await fi.image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) {
throw Exception("Failed to convert image to bytes.");
}
return BitmapDescriptor.fromBytes(byteData.buffer.asUint8List());
}
// Usage:
Future<void> _addCustomMarker() async {
final BitmapDescriptor customIcon = await _bitmapDescriptorFromAsset('assets/custom_marker.png', 100);
setState(() {
_markers.add(
Marker(
markerId: MarkerId(_center.toString()),
position: _center,
infoWindow: const InfoWindow(
title: 'My Location',
snippet: 'Custom marker example',
),
icon: customIcon,
),
);
});
}
Ensure you have added the asset to your pubspec.yaml
:
flutter:
assets:
- assets/custom_marker.png
Handling Map Events
The GoogleMap
widget provides various callbacks for handling map events, such as tapping on the map or moving the camera.
On Tap Event
The onTap
callback is called when the user taps on the map:
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
markers: _markers,
onTap: (LatLng latLng) {
print('Map tapped at: ${latLng.latitude}, ${latLng.longitude}');
},
)
On Camera Move Started
The onCameraMoveStarted
callback is called when the camera starts moving:
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
markers: _markers,
onCameraMoveStarted: () {
print('Camera move started');
},
)
Advanced Features
The google_maps_flutter
package also supports advanced features such as polylines, polygons, and circles.
Polylines
Display polylines on the map:
final Set<Polyline> _polylines = {
Polyline(
polylineId: PolylineId('route1'),
points: [
LatLng(45.521563, -122.677433),
LatLng(45.530000, -122.680000),
LatLng(45.540000, -122.690000),
],
width: 5,
color: Colors.blue,
),
};
// In GoogleMap widget
GoogleMap(
// ...
polylines: _polylines,
)
Polygons
Display polygons on the map:
final Set<Polygon> _polygons = {
Polygon(
polygonId: PolygonId('area1'),
points: [
LatLng(45.521563, -122.677433),
LatLng(45.530000, -122.680000),
LatLng(45.540000, -122.690000),
LatLng(45.510000, -122.660000),
],
fillColor: Colors.green.withOpacity(0.3),
strokeColor: Colors.green,
strokeWidth: 2,
),
};
// In GoogleMap widget
GoogleMap(
// ...
polygons: _polygons,
)
Circles
Display circles on the map:
final Set<Circle> _circles = {
Circle(
circleId: CircleId('circle1'),
center: LatLng(45.521563, -122.677433),
radius: 500,
fillColor: Colors.red.withOpacity(0.3),
strokeColor: Colors.red,
strokeWidth: 2,
),
};
// In GoogleMap widget
GoogleMap(
// ...
circles: _circles,
)
Troubleshooting
Here are some common issues and their solutions:
- Map Not Displaying:
- Ensure you have correctly configured the API key in your
AndroidManifest.xml
(Android) orAppDelegate.swift
(iOS). - Verify that the API key has the necessary permissions enabled in the Google Cloud Platform.
- Markers Not Appearing:
- Confirm that the coordinates for the markers are valid.
- Check if the
markers
property of theGoogleMap
widget is correctly set. - GoogleMapController Not Working:
- Make sure that the
onMapCreated
callback is properly assigning theGoogleMapController
. - Verify that you are calling
setState
when updating the markers.
Conclusion
The google_maps_flutter
package is a versatile tool for integrating Google Maps into your Flutter applications. By following this comprehensive guide, you can easily display maps, add markers, customize the map’s appearance, and handle map events. Whether you’re building a travel app, a location-based service, or any other application that requires mapping functionality, google_maps_flutter
is a great choice for implementing these features.