Toggle Map Interactions in Flutter
This tutorial shows how to enable and disable individual map interactions like zoom, pan, rotate, and tilt at runtime.
Prerequisites
Before you begin, ensure you have:
- Completed the Flutter Setup Guide
- A MapMetrics API key and style URL from the MapMetrics Portal
Complete Example: Interaction Control Panel
A full control panel that lets users toggle each gesture type independently:
dart
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';
class ToggleInteractionsScreen extends StatefulWidget {
@override
_ToggleInteractionsScreenState createState() => _ToggleInteractionsScreenState();
}
class _ToggleInteractionsScreenState extends State<ToggleInteractionsScreen> {
MapMetricsController? mapController;
bool zoomGestures = true;
bool scrollGestures = true;
bool rotateGestures = true;
bool tiltGestures = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Toggle Interactions'),
actions: [
TextButton(
onPressed: _enableAll,
child: Text('All ON', style: TextStyle(color: Colors.white)),
),
TextButton(
onPressed: _disableAll,
child: Text('All OFF', style: TextStyle(color: Colors.white70)),
),
],
),
body: Column(
children: [
// Interaction toggles
Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
color: Colors.grey[100],
child: Column(
children: [
_interactionToggle(
'Zoom (pinch)',
Icons.zoom_in,
zoomGestures,
(v) => setState(() => zoomGestures = v),
),
_interactionToggle(
'Scroll (pan)',
Icons.pan_tool,
scrollGestures,
(v) => setState(() => scrollGestures = v),
),
_interactionToggle(
'Rotate (two-finger)',
Icons.rotate_right,
rotateGestures,
(v) => setState(() => rotateGestures = v),
),
_interactionToggle(
'Tilt (two-finger vertical)',
Icons.view_in_ar,
tiltGestures,
(v) => setState(() => tiltGestures = v),
),
],
),
),
// Map
Expanded(
child: MapMetrics(
styleUrl: 'https://gateway.mapmetrics.org/styles/YOUR_STYLE_ID?token=YOUR_API_KEY',
onMapCreated: (controller) => mapController = controller,
initialCameraPosition: CameraPosition(
target: LatLng(48.8566, 2.3522),
zoom: 13.0,
),
zoomGesturesEnabled: zoomGestures,
scrollGesturesEnabled: scrollGestures,
rotateGesturesEnabled: rotateGestures,
tiltGesturesEnabled: tiltGestures,
),
),
],
),
);
}
Widget _interactionToggle(
String label,
IconData icon,
bool value,
ValueChanged<bool> onChanged,
) {
return SwitchListTile(
title: Row(
children: [
Icon(icon, size: 20, color: value ? Colors.blue : Colors.grey),
SizedBox(width: 8),
Text(label, style: TextStyle(fontSize: 14)),
],
),
value: value,
onChanged: onChanged,
dense: true,
contentPadding: EdgeInsets.symmetric(horizontal: 8),
);
}
void _enableAll() {
setState(() {
zoomGestures = true;
scrollGestures = true;
rotateGestures = true;
tiltGestures = true;
});
}
void _disableAll() {
setState(() {
zoomGestures = false;
scrollGestures = false;
rotateGestures = false;
tiltGestures = false;
});
}
}Presentation Mode
A common use case: lock all interactions for a presentation or kiosk display, then unlock with a button:
dart
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';
class PresentationModeScreen extends StatefulWidget {
@override
_PresentationModeScreenState createState() => _PresentationModeScreenState();
}
class _PresentationModeScreenState extends State<PresentationModeScreen> {
MapMetricsController? mapController;
bool isLocked = true;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
MapMetrics(
styleUrl: 'https://gateway.mapmetrics.org/styles/YOUR_STYLE_ID?token=YOUR_API_KEY',
onMapCreated: (controller) => mapController = controller,
initialCameraPosition: CameraPosition(
target: LatLng(48.8566, 2.3522),
zoom: 13.0,
),
zoomGesturesEnabled: !isLocked,
scrollGesturesEnabled: !isLocked,
rotateGesturesEnabled: !isLocked,
tiltGesturesEnabled: !isLocked,
),
// Lock indicator and toggle
Positioned(
top: 50,
right: 16,
child: GestureDetector(
onTap: () => setState(() => isLocked = !isLocked),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: isLocked ? Colors.red : Colors.green,
borderRadius: BorderRadius.circular(20),
boxShadow: [BoxShadow(color: Colors.black26, blurRadius: 4)],
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
isLocked ? Icons.lock : Icons.lock_open,
color: Colors.white,
size: 16,
),
SizedBox(width: 6),
Text(
isLocked ? 'Locked' : 'Unlocked',
style: TextStyle(color: Colors.white, fontSize: 13),
),
],
),
),
),
),
],
),
);
}
}Interaction Properties Reference
| Property | Gesture | Default |
|---|---|---|
zoomGesturesEnabled | Pinch-to-zoom, double-tap zoom | true |
scrollGesturesEnabled | Drag/pan to move the map | true |
rotateGesturesEnabled | Two-finger rotation | true |
tiltGesturesEnabled | Two-finger vertical swipe (3D tilt) | true |
Next Steps
- Disable Scroll Zoom — Focus on zoom control for embedded maps
- Navigation Controls — Add UI buttons when gestures are off
- Map Interactions — Full interaction handling with events
Tip: When disabling gestures, always provide alternative controls (buttons, sliders) so users can still navigate the map.