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.xmlfile. - 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.swiftfile. - Add the following code at the top of the
applicationmethod:
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:
MapScreenis a stateful widget that holds the map.GoogleMapControlleris used to control the map._centeris the initial latitude and longitude of the map’s center._onMapCreatedis a callback function that’s called when the map is created. It provides aGoogleMapControllerinstance, which you can use to interact with the map.GoogleMapis the widget that displays the map. It takes aninitialCameraPositionproperty 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:
_markersis aSet<Marker>that holds the map markers.- Inside the
_onMapCreatedmethod, aMarkeris created and added to the_markersset. - The
Markerconstructor takes several properties, includingmarkerId,position,infoWindow, andicon. - The
markersproperty of theGoogleMapwidget is set to the_markersset.
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
markersproperty of theGoogleMapwidget is correctly set. - GoogleMapController Not Working:
- Make sure that the
onMapCreatedcallback is properly assigning theGoogleMapController. - Verify that you are calling
setStatewhen 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.