[{"data":1,"prerenderedAt":75},["ShallowReactive",2],{"tutorial-integrare-google-maps-in-flutter-con-google-maps-flutter":3,"comments-tutorial-integrare-google-maps-in-flutter-con-google-maps-flutter":74},{"id":4,"title":5,"slug":6,"excerpt":7,"intro":8,"cover_image":9,"video_url":10,"difficulty":11,"estimated_minutes":12,"flutter_version":13,"status":14,"published_at":15,"meta_title":16,"meta_description":17,"category":18,"author":22,"steps":24},41,"Integrare Google Maps in Flutter con google_maps_flutter","integrare-google-maps-in-flutter-con-google-maps-flutter","Impara a mostrare una mappa interattiva, aggiungere marker personalizzati e gestire la posizione dell'utente in Flutter usando il pacchetto ufficiale google_maps_flutter.","Le mappe sono un componente fondamentale in moltissime app: dalla ricerca di locali alla visualizzazione di percorsi. In questo tutorial vedremo come integrare **Google Maps** in un'app Flutter utilizzando il pacchetto ufficiale `google_maps_flutter`.\n\nPartiremo dalla configurazione delle chiavi API su Android e iOS, mostreremo una mappa interattiva, aggiungeremo dei marker personalizzati e infine gestiremo la posizione dell'utente centrando la camera sulle coordinate desiderate.\n\n> **Prerequisiti:** un progetto Flutter funzionante, un account Google Cloud con la fatturazione attiva per generare le chiavi API.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Ftutorials\u002Fd4d5579a-4b8c-45b3-aabe-0a1548067477.jpg",null,"intermediate",40,"3.x","published","2026-07-17T04:30:51+00:00","Google Maps in Flutter con google_maps_flutter","Guida pratica per integrare Google Maps in Flutter: configurazione API, mappa interattiva, marker personalizzati e gestione della posizione.",{"id":19,"name":20,"slug":21},1,"Guide","guide",{"id":19,"name":23},"Flutter Bot",[25,31,39,47,54,61,68],{"id":26,"position":19,"title":27,"body":28,"code_snippet":10,"code_language":29,"expected_result":30,"demo_url":10,"video_url":10},275,"Ottenere le chiavi API di Google Maps","Prima di scrivere codice serve una chiave API valida.\n\n1. Vai sulla [Google Cloud Console](https:\u002F\u002Fconsole.cloud.google.com\u002F).\n2. Crea un nuovo progetto (o selezionane uno esistente).\n3. Abilita le API: **Maps SDK for Android** e **Maps SDK for iOS**.\n4. Vai su *Credenziali* → *Crea credenziali* → *Chiave API*.\n5. Copia la chiave generata: la useremo nei prossimi passi.\n\n> È consigliato limitare la chiave per applicazione (package name + SHA-1 per Android, bundle ID per iOS) per motivi di sicurezza.","dart","Hai una chiave API valida con Maps SDK abilitato per Android e iOS.",{"id":32,"position":33,"title":34,"body":35,"code_snippet":36,"code_language":37,"expected_result":38,"demo_url":10,"video_url":10},276,2,"Aggiungere la dipendenza al progetto","Aggiungi il pacchetto `google_maps_flutter` al tuo `pubspec.yaml`. Aggiungiamo anche `geolocator` che useremo più avanti per la posizione dell'utente.","dependencies:\n  flutter:\n    sdk: flutter\n  google_maps_flutter: ^2.9.0\n  geolocator: ^13.0.1","yaml","Dopo `flutter pub get` i pacchetti sono installati senza errori.",{"id":40,"position":41,"title":42,"body":43,"code_snippet":44,"code_language":45,"expected_result":46,"demo_url":10,"video_url":10},277,3,"Configurare Android e iOS","**Android** — Apri `android\u002Fapp\u002Fsrc\u002Fmain\u002FAndroidManifest.xml` e inserisci la chiave dentro il tag `\u003Capplication>`.\n\nAssicurati inoltre che `minSdkVersion` sia almeno **21** in `android\u002Fapp\u002Fbuild.gradle`.\n\n**iOS** — Apri `ios\u002FRunner\u002FAppDelegate.swift` e registra la chiave prima del `return`.\n\nAggiungi anche i permessi di localizzazione (li useremo più avanti) in `ios\u002FRunner\u002FInfo.plist`:\n\n```xml\n\u003Ckey>NSLocationWhenInUseUsageDescription\u003C\u002Fkey>\n\u003Cstring>L'app usa la posizione per mostrarla sulla mappa\u003C\u002Fstring>\n```","\u003C!-- AndroidManifest.xml, dentro \u003Capplication> -->\n\u003Cmeta-data\n    android:name=\"com.google.android.geo.API_KEY\"\n    android:value=\"LA_TUA_CHIAVE_API\"\u002F>\n\n\u002F\u002F AppDelegate.swift\nimport GoogleMaps\n\n@main\n@objc class AppDelegate: FlutterAppDelegate {\n  override func application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n  ) -> Bool {\n    GMSServices.provideAPIKey(\"LA_TUA_CHIAVE_API\")\n    GeneratedPluginRegistrant.register(with: self)\n    return super.application(application, didFinishLaunchingWithOptions: launchOptions)\n  }\n}","xml","Le piattaforme sono configurate con la chiave API e i permessi necessari.",{"id":48,"position":49,"title":50,"body":51,"code_snippet":52,"code_language":29,"expected_result":53,"demo_url":10,"video_url":10},278,4,"Mostrare la prima mappa interattiva","Creiamo un widget `StatefulWidget` che mostra un `GoogleMap` centrato su una posizione iniziale. Usiamo un `Completer` per ottenere il controller della mappa, utile per manipolare la camera in seguito.\n\nLa proprietà `initialCameraPosition` definisce dove parte la mappa: `target` sono le coordinate e `zoom` il livello di ingrandimento.","import 'dart:async';\nimport 'package:flutter\u002Fmaterial.dart';\nimport 'package:google_maps_flutter\u002Fgoogle_maps_flutter.dart';\n\nclass MapScreen extends StatefulWidget {\n  const MapScreen({super.key});\n\n  @override\n  State\u003CMapScreen> createState() => _MapScreenState();\n}\n\nclass _MapScreenState extends State\u003CMapScreen> {\n  final Completer\u003CGoogleMapController> _controller = Completer();\n\n  static const CameraPosition _initialPosition = CameraPosition(\n    target: LatLng(45.4642, 9.1900), \u002F\u002F Milano\n    zoom: 13,\n  );\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(title: const Text('Google Maps')),\n      body: GoogleMap(\n        initialCameraPosition: _initialPosition,\n        myLocationButtonEnabled: false,\n        onMapCreated: (controller) => _controller.complete(controller),\n      ),\n    );\n  }\n}","Avviando l'app vedi una mappa interattiva centrata su Milano, con zoom e pan funzionanti.",{"id":55,"position":56,"title":57,"body":58,"code_snippet":59,"code_language":29,"expected_result":60,"demo_url":10,"video_url":10},279,5,"Aggiungere marker personalizzati","Un marker rappresenta un punto di interesse sulla mappa. Ogni marker ha un `markerId` univoco, una posizione e opzionalmente una `InfoWindow` che appare al tocco.\n\nAggiungiamo un `Set\u003CMarker>` allo stato e lo passiamo alla proprietà `markers` del `GoogleMap`. Con `BitmapDescriptor.defaultMarkerWithHue` possiamo cambiarne il colore.","final Set\u003CMarker> _markers = {\n  const Marker(\n    markerId: MarkerId('duomo'),\n    position: LatLng(45.4641, 9.1919),\n    infoWindow: InfoWindow(\n      title: 'Duomo di Milano',\n      snippet: 'Piazza del Duomo',\n    ),\n  ),\n  Marker(\n    markerId: const MarkerId('castello'),\n    position: const LatLng(45.4705, 9.1795),\n    icon: BitmapDescriptor.defaultMarkerWithHue(\n      BitmapDescriptor.hueGreen,\n    ),\n    infoWindow: const InfoWindow(title: 'Castello Sforzesco'),\n  ),\n};\n\n\u002F\u002F Nel widget GoogleMap aggiungi:\n\u002F\u002F markers: _markers,","Sulla mappa compaiono due marker; toccandoli si apre la InfoWindow con titolo e descrizione.",{"id":62,"position":63,"title":64,"body":65,"code_snippet":66,"code_language":29,"expected_result":67,"demo_url":10,"video_url":10},280,6,"Ottenere la posizione dell'utente e centrare la camera","Usiamo `geolocator` per richiedere i permessi e ottenere la posizione corrente. Poi animiamo la camera verso quelle coordinate con `animateCamera` e aggiungiamo un marker sulla posizione dell'utente.\n\nRicorda di gestire il caso in cui i permessi vengano negati.","import 'package:geolocator\u002Fgeolocator.dart';\n\nFuture\u003Cvoid> _goToUserLocation() async {\n  \u002F\u002F Verifica e richiede i permessi\n  LocationPermission permission = await Geolocator.checkPermission();\n  if (permission == LocationPermission.denied) {\n    permission = await Geolocator.requestPermission();\n    if (permission == LocationPermission.denied) return;\n  }\n  if (permission == LocationPermission.deniedForever) return;\n\n  final position = await Geolocator.getCurrentPosition();\n  final controller = await _controller.future;\n\n  await controller.animateCamera(\n    CameraUpdate.newCameraPosition(\n      CameraPosition(\n        target: LatLng(position.latitude, position.longitude),\n        zoom: 15,\n      ),\n    ),\n  );\n\n  setState(() {\n    _markers.add(\n      Marker(\n        markerId: const MarkerId('me'),\n        position: LatLng(position.latitude, position.longitude),\n        infoWindow: const InfoWindow(title: 'Sei qui'),\n      ),\n    );\n  });\n}\n\n\u002F\u002F Aggiungi un FloatingActionButton allo Scaffold:\n\u002F\u002F floatingActionButton: FloatingActionButton(\n\u002F\u002F   onPressed: _goToUserLocation,\n\u002F\u002F   child: const Icon(Icons.my_location),\n\u002F\u002F ),","Premendo il pulsante la mappa si sposta con un'animazione sulla posizione reale dell'utente, mostrando un marker 'Sei qui'.",{"id":69,"position":70,"title":71,"body":72,"code_snippet":10,"code_language":29,"expected_result":73,"demo_url":10,"video_url":10},281,7,"Buone pratiche e conclusioni","Hai integrato Google Maps in Flutter con successo! Alcuni consigli finali:\n\n- **Sicurezza chiavi:** limita sempre le chiavi API per package\u002Fbundle e SHA-1 e monitora l'utilizzo nella console per evitare costi imprevisti.\n- **Performance:** con molti marker valuta il *clustering* usando pacchetti come `google_maps_cluster_manager`.\n- **Permessi:** mostra all'utente una spiegazione chiara prima di richiedere la posizione.\n- **Stili personalizzati:** puoi applicare uno stile custom alla mappa con `controller.setMapStyle(jsonString)` generato da [Snazzy Maps](https:\u002F\u002Fsnazzymaps.com\u002F).\n\nCon queste basi puoi costruire funzionalità avanzate come tracciamento di percorsi (`Polyline`), aree evidenziate (`Polygon`) e ricerca di luoghi tramite le Places API.","Hai un'app funzionante con mappa interattiva, marker e geolocalizzazione, pronta per essere estesa.",[],1785219607953]