A Flutter package powered by OpenStreetMap for free map, autocomplete places textfield, polylines drawing, geocoding, and reverse geocoding.

Features

  • Address Search: Perform address searches with autocomplete textfield.
  • Map Features: Add markers, draw polylines, select location on tap, and fine control map using controller.
  • Geocoding: Get geographic coordinates from an address.
  • Reverse Geocoding: Retrieve addresses from geographic coordinates.
  • Powered by OpenStreetMap: A free, open-source alternative to Google Maps.
  • Highly Customizable: Adjust the widgets appearance to match your app’s design.

free_map screenshot

Getting started

Android

  1. Add Internet permission in your AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET" />

Usage

Auto-complete text field

⚠️ Usage Warnings:
Nominatim enforces a strict rate limit of 1 request per second per application (not per device or IP).
During periods of high traffic, this may cause requests to slow down.
If your app heavily relies on map features, it is recommended to use a self-hosted Nominatim server or a third-party provider as a fallback.
Check full Usage Policy here.

FmSearchField(
    selectedValue: _address,
    searchParams: const FmSearchParams(),
    onSelected: (data) => _address = data,
    textFieldBuilder: (focus, controller, onChanged) {
        return TextFormField(
            focusNode: focus,
            onChanged: onChanged,
            controller: controller,
            decoration: InputDecoration(
              filled: true,
              hintText: 'Search',
              fillColor: Colors.grey[300],
              suffixIcon: controller.text.trim().isEmpty || !focus.hasFocus
                  ? null
                  : IconButton(
                      padding: EdgeInsets.zero,
                      icon: const Icon(Icons.close),
                      onPressed: controller.clear,
                      visualDensity: VisualDensity.compact,
                    ),
            ),
          );
        },
)

Map Widget

⚠️ Usage Warnings:
The default OpenStreetMap public tile servers are not intended for production use.
They are shared resources with strict usage policies and limited capacity.
If your app is deployed at scale, you must configure a dedicated tile provider.
We recommend setting a custom urlTemplate in FmMap to use either:
Your own self-hosted tile server, or
A third-party provider (e.g., MapTiler, Mapbox, Carto). Check full Usage Policy here.

FmMap(
    mapController: _mapController,
    mapOptions: MapOptions(
        minZoom: 15,
        maxZoom: 18,
        initialZoom: 15,
        initialCenter: _src,
        onTap: (pos, point) => _getAddress(point),
    ),
    markers: [
        Marker(
          point: _src,
          child: const Icon(
            size: 40.0,
            color: Colors.red,
            Icons.location_on_rounded,
          ),
        ),
        Marker(
          point: _dest,
          child: const Icon(
            size: 40.0,
            color: Colors.blue,
            Icons.location_on_rounded,
          ),
        ),
    ],
    polylineOptions: const FmPolylineOptions(
        strokeWidth: 3,
        color: Colors.blue,
    ),
),

Geocoding

final data = await FmService().getGeocode(address: address);

Reverse Geocoding

final data = await FmService().getAddress(
    lat: pos.latitude,
    lng: pos.longitude,
);

Additional information

Think you've found a bug, or would like to see a new feature? We'd love to hear about it! Visit the Issues section of the git repository.