Locate the User in Flutter
Show the user's current GPS location on the map. This guide covers enabling the built-in location layer and requesting location permissions on both Android and iOS.
Prerequisites
Before you begin, ensure you have:
- Completed the Flutter Setup Guide (includes platform permission setup)
- A MapMetrics API key and style URL from the MapMetrics Portal
Platform Permissions
Android
Add these permissions to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />iOS
Add these keys to ios/Runner/Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to your location to show it on the map.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to your location to show it on the map.</string>Basic User Location
Enable the built-in location dot on the map:
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';
class LocateUserScreen extends StatefulWidget {
@override
_LocateUserScreenState createState() => _LocateUserScreenState();
}
class _LocateUserScreenState extends State<LocateUserScreen> {
MapMetricsController? mapController;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('My Location')),
body: MapMetrics(
styleUrl: 'https://gateway.mapmetrics.org/styles/YOUR_STYLE_ID?token=YOUR_API_KEY',
onMapCreated: (MapMetricsController controller) {
mapController = controller;
},
initialCameraPosition: CameraPosition(
target: LatLng(48.8566, 2.3522),
zoom: 4.0,
),
myLocationEnabled: true,
myLocationTrackingMode: MyLocationTrackingMode.Tracking,
myLocationRenderMode: MyLocationRenderMode.COMPASS,
),
floatingActionButton: FloatingActionButton(
onPressed: _goToMyLocation,
child: Icon(Icons.my_location),
),
);
}
void _goToMyLocation() {
mapController?.animateCamera(
CameraUpdate.zoomTo(15.0),
);
}
}The blue dot appears at the user's current location, and the compass arrow shows the direction they are facing.
Location Tracking Modes
| Mode | Description |
|---|---|
MyLocationTrackingMode.None | Shows location dot but doesn't move the camera |
MyLocationTrackingMode.Tracking | Camera follows the user as they move |
MyLocationTrackingMode.TrackingCompass | Camera follows and rotates to match user heading |
MyLocationTrackingMode.TrackingGPS | Camera follows with GPS bearing |
Location Render Modes
| Mode | Description |
|---|---|
MyLocationRenderMode.NORMAL | Simple blue dot |
MyLocationRenderMode.COMPASS | Blue dot with compass heading arrow |
MyLocationRenderMode.GPS | Blue dot with GPS bearing indicator |
Complete Example: Locate Me Button
A complete example with a "Locate Me" button that requests permission and flies to the user's location:
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';
class LocateMeScreen extends StatefulWidget {
@override
_LocateMeScreenState createState() => _LocateMeScreenState();
}
class _LocateMeScreenState extends State<LocateMeScreen> {
MapMetricsController? mapController;
String statusMessage = 'Tap the button to find your location';
bool isLocating = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Locate Me')),
body: Column(
children: [
// Status bar
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
color: Colors.grey[100],
child: Row(
children: [
if (isLocating)
Padding(
padding: EdgeInsets.only(right: 8),
child: SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
),
),
Expanded(child: Text(statusMessage)),
],
),
),
// Map
Expanded(
child: MapMetrics(
styleUrl: 'https://gateway.mapmetrics.org/styles/YOUR_STYLE_ID?token=YOUR_API_KEY',
onMapCreated: (MapMetricsController controller) {
mapController = controller;
},
onUserLocationUpdated: (UserLocation location) {
setState(() {
isLocating = false;
statusMessage =
'Lat: ${location.position.latitude.toStringAsFixed(5)}, '
'Lng: ${location.position.longitude.toStringAsFixed(5)}';
});
},
initialCameraPosition: CameraPosition(
target: LatLng(0.0, 0.0),
zoom: 2.0,
),
myLocationEnabled: true,
myLocationTrackingMode: MyLocationTrackingMode.None,
),
),
],
),
floatingActionButton: FloatingActionButton.extended(
onPressed: _locateMe,
icon: Icon(Icons.my_location),
label: Text('Locate Me'),
),
);
}
void _locateMe() {
setState(() {
isLocating = true;
statusMessage = 'Getting your location...';
});
// Enable tracking and fly to user
mapController?.animateCamera(
CameraUpdate.zoomTo(15.0),
);
}
}Handling Permission Errors
Always handle the case where the user denies location permission:
MapMetrics(
// ... other properties
myLocationEnabled: true,
onError: (String error) {
if (error.contains('location') || error.contains('permission')) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Location Permission Required'),
content: Text(
'Please enable location permissions in your device settings '
'to use this feature.',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('OK'),
),
],
),
);
}
},
)Next Steps
- Fly to a Location — Animate the camera to any coordinates
- Add a Popup — Show info when tapping markers
- Map Interactions — Handle taps, long presses, and gestures
Note: Location only works on physical devices or emulators with location simulation enabled. It also requires HTTPS in production web builds.