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.
Getting started
Android
- 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 customurlTemplate
inFmMap
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.