Newby Coder header banner

Flutter Google Maps

In Flutter, google maps can be integrated by using google_maps_flutter package

It provides a GoogleMap widget which can be used to

Implementation

Importing Package

Import the package into dart code

import 'package:google_maps_flutter/google_maps_flutter.dart';

Check current status

Code snippet of GoogleMap widget

void onMapCreated(GoogleMapController controller) {
  setState(() {
    _controller = controller;
  });
}
static final CameraPosition _kInitialPosition = const CameraPosition(
    target: LatLng(-29.84, 31.04),
    zoom: 10.66,
);
GoogleMap googleMap = GoogleMap(
  onMapCreated: onMapCreated,
  initialCameraPosition: _kInitialPosition,
  cameraTargetBounds: _cameraTargetBounds,
  minMaxZoomPreference: _minMaxZoomPreference,
  mapType: _mapType,
  trafficEnabled: _trafficEnabled,
  onCameraMove: _updateCameraPosition,
);

Creating new Flutter App

Check Flutter installation to setup Flutter

Use flutter create command to create a Flutter project (here nc_google_maps_app) :

flutter create nc_google_maps_app

Dependency

Adding API Key

A API key can be generated from a project under a Google developer account

Create a project or select existing project

Go to Google cloud console and log in with a Google account

If not created already, go to https://console.cloud.google.com/projectcreate to create a project

Projects should appear in the top left corner drop-down, including Firebase projects

google-cloud-select-project

Select project from the dropdown

Enable Google maps API

Goto https://console.cloud.google.com/google/maps-apis

Alternatively, search for Maps SDK for Android

Click on the Enable button

google-cloud-enable-google-maps-api

Generate Api key

Go to https://console.cloud.google.com/apis/credentials

Navigate to Create Credentials and click on API key

google-cloud-create-credentials-api-key

Copy Api key to be added to manifest

google-cloud-copy-api-key-for-maps

Add API key to AndroidManifest.xml

Add Api key as meta-data inside application tag as highlighted

Here NcGoogleMapsApp is React native project name

NcGoogleMapsApp/android/app/src/main/AndroidManifest.xml
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="nc_google_maps_app"
        android:icon="@mipmap/ic_launcher">
      <meta-data android:name="com.google.android.geo.API_KEY"
             android:value="AIzaSyBg-g9QZMHSmmnPOC-lTC4QnCjClgfTGaI"/>

App Code

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


void main() {
  runApp(MaterialApp(home: GoogleMapWidget()));
}

class GoogleMapWidget extends StatefulWidget {
  GoogleMapWidget() : super();

  @override
  State<StatefulWidget> createState() => GoogleMapWidgetState();
}

class GoogleMapWidgetState extends State<GoogleMapWidget> {
  GoogleMapWidgetState();
  final LatLngBounds durbanBounds = LatLngBounds(
    southwest: const LatLng(-30, 30.7),
    northeast: const LatLng(-29.7, 31.22),
  );
  static final CameraPosition _kInitialPosition = const CameraPosition(
    target: LatLng(-29.84, 31.04),
    zoom: 10.66,
  );

  CameraPosition _position = _kInitialPosition;
  bool _isMapCreated = false;
  CameraTargetBounds _cameraTargetBounds = CameraTargetBounds.unbounded;
  MinMaxZoomPreference _minMaxZoomPreference = MinMaxZoomPreference.unbounded;
  MapType _mapType = MapType.normal;
  bool _trafficEnabled = false;
  GoogleMapController _controller;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  Widget _latLngBoundsToggler() {
    return FlatButton(
      child: Text(
        _cameraTargetBounds.bounds == null
            ? 'bound camera target'
            : 'release camera target',
      ),
      onPressed: () {
        setState(() {
          _cameraTargetBounds = _cameraTargetBounds.bounds == null
              ? CameraTargetBounds(durbanBounds)
              : CameraTargetBounds.unbounded;
        });
      },
    );
  }

  Widget _zoomBoundsToggler() {
    return FlatButton(
      child: Text(_minMaxZoomPreference.minZoom == null
          ? 'bound zoom'
          : 'release zoom'),
      onPressed: () {
        setState(() {
          _minMaxZoomPreference = _minMaxZoomPreference.minZoom == null
              ? const MinMaxZoomPreference(12.0, 16.0)
              : MinMaxZoomPreference.unbounded;
        });
      },
    );
  }

  // Get nextType and assign to button press
  Widget _mapTypeCycler() {
    final MapType nextType =
        MapType.values[(_mapType.index + 1) % MapType.values.length];
    return FlatButton(
      child: Text('change map type to $nextType'),
      onPressed: () {
        setState(() {
          _mapType = nextType;
        });
      },
    );
  }

  Widget _trafficToggler() {
    return FlatButton(
      child: Text('${_trafficEnabled ? 'disable' : 'enable'} traffic'),
      onPressed: () {
        setState(() {
          _trafficEnabled = !_trafficEnabled;
        });
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    final GoogleMap googleMap = GoogleMap(
      onMapCreated: onMapCreated,
      initialCameraPosition: _kInitialPosition,
      cameraTargetBounds: _cameraTargetBounds,
      minMaxZoomPreference: _minMaxZoomPreference,
      mapType: _mapType,
      trafficEnabled: _trafficEnabled,
      onCameraMove: _updateCameraPosition,
    );

    final List<Widget> columnChildren = <Widget>[
      Padding(
        padding: const EdgeInsets.all(10.0),
        child: Center(
          child: SizedBox(
            width: 400.0,
            height: 300.0,
            child: googleMap,
          ),
        ),
      ),
    ];

    if (_isMapCreated) {
      columnChildren.add(
        Expanded(
          child: ListView(
            children: <Widget>[
              Text(
                  'camera position: ${_position.target.latitude.toStringAsFixed(4)},'
                  '${_position.target.longitude.toStringAsFixed(4)}'),
              Text('zoom: ${_position.zoom}'),
              _latLngBoundsToggler(),
              _mapTypeCycler(),
              _zoomBoundsToggler(),
              _trafficToggler(),
            ],
          ),
        ),
      );
    }
    return Scaffold(
      appBar: AppBar(
        title: Text("Google maps Example App"),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: columnChildren,
      ),
    );
  }

  void _updateCameraPosition(CameraPosition position) {
    setState(() {
      _position = position;
    });
  }

  void onMapCreated(GoogleMapController controller) {
    setState(() {
      _controller = controller;
      _isMapCreated = true;
    });
  }
}

Run instructions

Ensure a supported device is connected or emulator is started

Go to project directory

Use flutter run command to run

flutter run

It builds and runs app on an available android/ios device

cl-android-flutter-google-maps-as1cl-android-flutter-google-maps-as2