Skip to content

Both copy text to your clipboard — Build with AI copies a setup prompt to paste into Claude Code, Cursor, Codex or Copilot; Copy page as Markdown copies this page to paste into a chat. How it works

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:

A Note on Gesture Control ​

There are no individual zoomGesturesEnabled/scrollGesturesEnabled/rotateGesturesEnabled/tiltGesturesEnabled parameters on MapMetricsView. Instead, MapOptions.gestures takes a single MapGestures object with rotate, pan, zoom, and pitch booleans. Rebuild it (via setState) whenever you want to flip a gesture — the map picks up the new MapGestures on the next MapOptions it receives, same as any other declarative widget property.

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> {
  MapController? 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: MapMetricsView(
              options: MapOptions(
                initStyle:
                    'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY',
                initCenter: Position(2.3522, 48.8566), // lng, lat — Paris
                initZoom: 13.0,
                gestures: MapGestures(
                  zoom: zoomGestures,
                  pan: scrollGestures,
                  rotate: rotateGestures,
                  pitch: tiltGestures,
                ),
              ),
              onMapCreated: (controller) => mapController = controller,
            ),
          ),
        ],
      ),
    );
  }

  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> {
  MapController? mapController;
  bool isLocked = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          MapMetricsView(
            options: MapOptions(
              initStyle:
                  'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY',
              initCenter: Position(2.3522, 48.8566),
              initZoom: 13.0,
              gestures: isLocked ? const MapGestures.none() : const MapGestures.all(),
            ),
            onMapCreated: (controller) => mapController = controller,
          ),
          // 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 ​

MapGestures fieldGestureDefault (MapGestures.all())
zoomPinch-to-zoom, double-tap zoomtrue
panDrag/pan to move the maptrue
rotateTwo-finger rotationtrue
pitchTwo-finger vertical swipe (3D tilt)true

Next Steps ​


Tip: When disabling gestures, always provide alternative controls (buttons, sliders) so users can still navigate the map.