Create a custom Map compass in Google Maps Flutter | by Rishi Singh | Nov, 2024

A poster with flutter logo on the left and a mobile screen with custom compass on the right
Custom Compass in Google Maps Flutter

In this article we will go through how to create a custom compass widget for Google Maps in Flutter. This compass will rotate as you rotate the map just like the default map compass.

Before we start, let’s ensure that you have a Flutter environment set up on your machine and you have added the google_maps_flutter package to pubspec.yaml file in your project. If not, here is how to do that:

  1. Create a new Flutter project
    flutter create custom_compass_app
  2. Add google_maps_flutter to your pubspec.yaml
    dependencies: google_maps_flutter: latest_version
  3. Run flutter pub get to install the package

We need to configure google_maps_flutter to render the map within our app. This involves basic setup and getting an API key from the Google Cloud Platform.

  1. Obtain a Google Maps API Key: You can follow the Google Maps Platform documentation to create a new project, enable Google Maps API for Android and iOS and generate an API key.
  2. Configure the API Key: Add the generated API key to the AndroidManifest.xml for Android and the AppDelegate.swift for iOS respectively.

Our first task is to create a GoogleMapController to manage the map. We’ll also set up the map to capture the bearing (rotation) as the camera moves or rotates.

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MapScreen(),
);
}
}

class MapScreen extends StatefulWidget {
const MapScreen({super.key});

@override
MapScreenState createState() => MapScreenState();
}

class MapScreenState extends State<MapScreen> {
late GoogleMapController _mapController;
double _bearing = 0.0;

// Method to set the map controller and listen for camera changes
void _onMapCreated(GoogleMapController controller) {
_mapController = controller;
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Custom Compass in Google Maps'),
),
body: Stack(
children: [
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: const CameraPosition(
target: LatLng(37.7749, -122.4194), // Initial location
zoom: 14.0,
),
onCameraMove: (position) {
setState(() {
_bearing = position.bearing;
});
},
),
Positioned(top: 20, right: 20, child: CompassWidget(bearing: _bearing)),
],
),
);
}
}

Let’s work on designing our CompassWidget that rotates based on the map’s bearing. We can use the Transform.rotate widget, which makes rotation simple and effective.

class CompassWidget extends StatelessWidget {
final double bearing;

const CompassWidget({super.key, required this.bearing});

@override
Widget build(BuildContext context) {
return Transform.rotate(
angle: bearing * (3.14159265359 / 180), // Convert bearing to radians
child: const Icon(Icons.navigation, color: Colors.blue, size: 50.0),
);
}
}

  1. Rotation Logic: Transform.rotate rotates the child widget based on the specified angle. Since Flutter expects the angle in radians, we convert the bearing from degrees using the formula: radians = degrees * (π / 180).
  2. Compass Design: The CompassWidget uses an Icon widget (Icons.navigation). We can replace this with a custom image asset for a unique look.

That’s it, you have learned how we can use Transform.rotate to rotate a widget given the angle in radians.

Thanks for reading this article ❤️
If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If you learned something new.

Leave a Reply