Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/liodali/osm_flutter

OpenStreetMap plugin for flutter
https://github.com/liodali/osm_flutter

dart flutter kotlin map osm osm-flutter swift web-support

Last synced: 5 days ago
JSON representation

OpenStreetMap plugin for flutter

Awesome Lists containing this project

README

        



# flutter_osm_plugin

![pub](https://img.shields.io/badge/pub-v1.3.5-blue)

## Platform Support
| Android | iOS | Web |
|:---:|:---:|:---:|
| supported :heavy_check_mark: | supported :heavy_check_mark: (min iOS supported : 13) | supported :heavy_check_mark: |

osm plugin for flutter apps

* current position (Android/iOS/web)
* change position (Android/iOS/web)
* create Marker manually (Android/iOS/web)
* tracking user location (Android/iOS/web)
* customize Icon Marker (Android/iOS/web)
* customize user Marker (Android/iOS/web)
* assisted selection position (Android/iOS)
* set BoundingBox (Android/iOS/Web)
* zoom into region (Android/iOS/web)
* draw Road (Android/iOS/web)
* draw dotted Road (Android/iOS/web)
* recuperate information (instruction/duration/distance) of the current road (Android/iOS/web)
* draw Road manually (Android/iOS/web)
* draw multiple Roads (Android/iOS/web)
* ClickListener on Marker (Android/iOS/web)
* ClickListener on Map (Android/iOS/web)
* calculate distance between 2 points
* address suggestion
* draw shapes (Android/iOS/web)
* simple dialog location picker (Android/iOS)
* listen to region change (Android/iOS/Web)
* set custom tiles (Android/iOS/Web)

## Getting Started
openStreetMap flutter examples



openStreetMap flutter examples



openStreetMap flutter examples

## Installing

Add the following to your `pubspec.yaml` file:

dependencies:
flutter_osm_plugin: ^1.3.5

## Integration with Hooks

> To use our map library with `Flutter_Hooks` library use our new extension library
https://pub.dev/packages/osm_flutter_hooks
many thanks for @ben-xD

### Migration to `0.41.2` (Android Only)

> open file build.gradle inside android file

* change kotlin version from `1.5.21` to `1.7.20`
* change gradle version from `7.0.4` to `7.1.3`
* change compileSdkVersion to 33

### Migration to `0.34.0` (Android Only)
> if you are using this plugin before Flutter 3

> you should make some modification in build.gradle before that run flutter clean && flutter pub get

> open file build.gradle inside android file

* change kotlin version from `1.5.21` to `1.6.21`
* change gradle version from `7.0.2` to `7.1.3` or `7.0.4`
* change compileSdkVersion to 32

### Migration to `0.16.0` (Android Only)
> if you are using this plugin before Flutter 2

> you should make some modification in build.gradle before that run flutter clean && flutter pub get

> open file build.gradle inside android file

* change kotlin version from `1.4.21` to `1.5.21`
* change gradle version from `4.1.1` to `7.0.2`

### For web integration

> To show buttons,UI that have to manage user click over the map, you should use this library : `pointer_interceptor`

## Simple Usage
#### Creating a basic `OSMFlutter` :


```dart
OSMFlutter(
controller:mapController,
osmOption: OSMOption(
userTrackingOption: UserTrackingOption(
enableTracking: true,
unFollowUser: false,
),
zoomOption: ZoomOption(
initZoom: 8,
minZoomLevel: 3,
maxZoomLevel: 19,
stepZoom: 1.0,
),
userLocationMarker: UserLocationMaker(
personMarker: MarkerIcon(
icon: Icon(
Icons.location_history_rounded,
color: Colors.red,
size: 48,
),
),
directionArrowMarker: MarkerIcon(
icon: Icon(
Icons.double_arrow,
size: 48,
),
),
),
roadConfiguration: RoadOption(
roadColor: Colors.yellowAccent,
),
markerOption: MarkerOption(
defaultMarker: MarkerIcon(
icon: Icon(
Icons.person_pin_circle,
color: Colors.blue,
size: 56,
),
)
),
)
);

```

## MapController

> Declare `MapController` to control OSM map

1) Initialisation

> **Note**
> using the default constructor, you should use `initMapWithUserPosition` or `initPosition`
> if you want the map to initialize using static position use the named constructor `withPosition`
> or if you want to initialize the map with user position use `withUserPosition`

```dart
// default constructor
MapController controller = MapController(
initPosition: GeoPoint(latitude: 47.4358055, longitude: 8.4737324),
areaLimit: BoundingBox(
east: 10.4922941,
north: 47.8084648,
south: 45.817995,
west: 5.9559113,
),
);
// or set manually init position
final controller = MapController.withPosition(
initPosition: GeoPoint(
latitude: 47.4358055,
longitude: 8.4737324,
),
);
// init the position using the user location
final controller = MapController.withUserPosition(
trackUserLocation: UserTrackingOption(
enableTracking: true,
unFollowUser: false,
)
)

// init the position using the user location and control map from outside
final controller = MapController.withUserPosition(
trackUserLocation: UserTrackingOption(
enableTracking: true,
unFollowUser: false,
),
useExternalTracking: true
)
```

2) Dispose

```dart
controller.dispose();
```

3) Properties of default `MapController`

> `MapController` has 2 named Constructor `MapController.withPosition`,
`MapController.withUserPosition` to control initialization of the Map

| Properties | Description |
| ---------------------------- | ----------------------------------------------------------------------- |
| `initMapWithUserPosition` | (UserTrackingOption?) initialize map with user position |
| `initPosition` | (GeoPoint) if it isn't null, the map will be pointed at this position |
| `areaLimit` | (Bounding) set area limit of the map (default BoundingBox.world()) |
| `customLayer` | (CustomTile) set customer layer using different osm server , this attribute used only with named constructor `customLayer` |
| ` useExternalTracking` | (bool) if true,we will disable our logic to show userlocation marker or to move to the user position |

3.1) Custom Layers with `MapController`

* To change the tile source in OSMFlutter, you should used our named constructor `customLayer`, see the example below

```dart

controller = MapController.customLayer(
initPosition: GeoPoint(
latitude: 47.4358055,
longitude: 8.4737324,
),
customTile: CustomTile(
sourceName: "opentopomap",
tileExtension: ".png",
minZoomLevel: 2,
maxZoomLevel: 19,
urlsServers: [
TileURLs(
//"https://tile.opentopomap.org/{z}/{x}/{y}"
url: "https://tile.opentopomap.org/",
subdomains: [],
)
],
tileSize: 256,
),
)

```

* also,you can use our predefined custom tiles like
* `cyclOSMLayer` constructor for cycling tiles
* `publicTransportationLayer` constructor for transport tiles ,it's public osm server
* we support full server path like `("https://tile.opentopomap.org/{z}/{x}/{y}")`

For more example see our example in `home_example.dart`




3.2) Change Layers in runtime

```dart
await controller.changeTileLayer(tileLayer: CustomTile(...));
```
4) Set map on user current location

```dart
await controller.currentLocation();

```
5) Zoom IN

```dart
await controller.setZoom(stepZoom: 2);
// or
await controller.zoomIn();
```

5.1) Zoom Out

```dart
await controller.setZoom(stepZoom: -2);
// or
await controller.zoomOut();

```
5.2) change zoom level

> `zoomLevel` should be between `minZoomLevel` and `maxZoomLevel`

```dart
await controller.setZoom(zoomLevel: 8);
```
5.3) zoom to specific bounding box

```dart
await controller.zoomToBoundingBox(BoundingBox(),paddingInPixel:0)
```

##### Note :

* For the box attribute ,If you don't have bounding box,you can use list of geopoint like this `BoundingBox.fromGeoPoints`

6) get current zoom level b>

```dart
await controller.getZoom();
```

7) BoundingBox

> set bounding box in the map

```dart
await controller.limitAreaMap(BoundingBox( east: 10.4922941, north: 47.8084648, south: 45.817995, west: 5.9559113,));
```
> remove bounding box in the map

```dart
await controller.removeLimitAreaMap();
```

8) Track user current position

> for iOS,you should add those line in your info.plist file
```text
NSLocationWhenInUseUsageDescription
any text you want
NSLocationAlwaysUsageDescription
any text you want
```
> from version 0.40.0 we can call only `enableTracking` will animate to user location
without need to call `currentLocation`

> when `enableStopFollow` is true,map will not be centered if the user location changed

> you can disable rotation of personIcon using [disableUserMarkerRotation] (default: false)

```dart
await controller.enableTracking(enableStopFollow:false,);
```
or

> use this method below if you want to control the map(move to the user location and show the marker) while receiving the user location

```dart
await controller.startLocationUpdating();
```
9) Disable tracking user position

```dart
await controller.disabledTracking();
```
or

> use this method below if you already used `startLocationUpdating`

```dart
await controller.stopLocationUpdating();
```

10) update the location

> Change the location without create marker

```dart
await controller.moveTo(GeoPoint(latitude: 47.35387, longitude: 8.43609),animate:true);
```

11) recuperation current position

```dart
GeoPoint geoPoint = await controller.myLocation();
```
12) get center map

```dart
GeoPoint centerMap = await controller.centerMap;
```
12.1) get geoPoint in the map

* recuperate geoPoint of marker add it by user except static points

```dart
List geoPoints = await controller.geopoints;
```
13) get bounding box map

```dart
BoundingBox bounds = await controller.bounds;
```

14) Map Listener

> Get GeoPoint from listener from controller directly
(for more example: see home_example.dart )

a.1) single tap listener
```dart
controller.listenerMapSingleTapping.addListener(() {
if (controller.listenerMapSingleTapping.value != null) {
/// put you logic here
}
});
```
a.2) long tap listener
```dart
controller.listenerMapLongTapping.addListener(() {
if (controller.listenerMapLongTapping.value != null) {
/// put you logic here
}
});
```
a.3) region change listener
```dart
controller.listenerRegionIsChanging.addListener(() {
if (controller.listenerRegionIsChanging.value != null) {
/// put you logic here
}
});
```
15) Create Marker Programmatically

> you can change marker icon by using attribute `markerIcon`
> the angle value should be between [0,2pi]
> set anchor of ther Marker

```dart
await controller.addMarker(GeoPoint,
markerIcon:MarkerIcon,
angle:pi/3,
anchor:IconAnchor(anchor: Anchor.top,)
);
```
15.1) Update Marker

> you can change the location,icon,angle,anchor of the specific marker

> The old configuration of the Marker will be keep it the same if not specificied

```dart
await controller.changeLocationMarker(oldGeoPoint,newGeoPoint,MarkerIcon,angle,IconAnchor);
```

15.2) Change Icon Marker

> You can change marker icon by using attribute `markerIcon` of existing Marker
> The GeoPoint/Marker should be exist

```dart
await controller.setMarkerIcon(GeoPoint,MarkerIcon);
```

15.3) Remove marker

```dart
await controller.removeMarker(geoPoint);
```
* PS : static position cannot be removed by this method

16) Draw road,recuperate instructions ,distance in km and duration in sec

> you can add an middle position to pass your route through them
> change configuration of the road in runtime
> zoom into the region of the road
> change the type of the road that user want to use

```dart
RoadInfo roadInfo = await controller.drawRoad(
GeoPoint(latitude: 47.35387, longitude: 8.43609),
GeoPoint(latitude: 47.4371, longitude: 8.6136),
roadType: RoadType.car,
intersectPoint : [ GeoPoint(latitude: 47.4361, longitude: 8.6156), GeoPoint(latitude: 47.4481, longitude: 8.6266)]
roadOption: RoadOption(
roadWidth: 10,
roadColor: Colors.blue,
zoomInto: true,
),
);
print("${roadInfo.distance}km");
print("${roadInfo.duration}sec");
print("${roadInfo.instructions}");
```

### properties of `RoadOption`

| Properties | Description |
| ------------------------ | ----------------------------------- |
| `roadColor` | (Color) required Field, change the default color of the route in runtime |
| `roadWidth` | (double) change the road width, default value 5.0 |
| `roadBorderColor` | (Color?) set color of border polyline |
| `roadBorderWidth` | (double?) set border width of polyline, if width null or 0,polyline will drawed without border |
| `zoomInto` | (bool) change zoom level to make the all the road visible (default:true) |
| `isDotted` | (bool) to draw dotted polyline (default: false) |

**Note** drawing dotted polyline has limitation on web where we cannot draw dotted poyline with borderWidth > 0

16.b) draw road manually
```dart
await controller.drawRoadManually(
waysPoint,
interestPointIcon: MarkerIcon(
icon: Icon(
Icons.location_history,
color: Colors.black,
),
),
interestPoints: [waysPoint[3],waysPoint[6]],
zoomInto: true
)
```

17) Delete last road

```dart
await controller.removeLastRoad();
```

18) draw multiple roads

```dart
final configs = [
MultiRoadConfiguration(
startPoint: GeoPoint(
latitude: 47.4834379430,
longitude: 8.4638911095,
),
destinationPoint: GeoPoint(
latitude: 47.4046149269,
longitude: 8.5046595453,
),
),
MultiRoadConfiguration(
startPoint: GeoPoint(
latitude: 47.4814981476,
longitude: 8.5244329867,
),
destinationPoint: GeoPoint(
latitude: 47.3982152237,
longitude: 8.4129691189,
),
roadOptionConfiguration: MultiRoadOption(
roadColor: Colors.orange,
)),
MultiRoadConfiguration(
startPoint: GeoPoint(
latitude: 47.4519015578,
longitude: 8.4371175094,
),
destinationPoint: GeoPoint(
latitude: 47.4321999727,
longitude: 8.5147623089,
),
),
];
await controller.drawMultipleRoad(
configs,
commonRoadOption: MultiRoadOption(
roadColor: Colors.red,
),
);

```

19) delete all roads

```dart
await controller.clearAllRoads();
```

20) Change static GeoPoint position

> add new staticPoints with empty list of geoPoints (notice: if you add static point without marker,they will get default maker used by plugin)

> change their position over time

> change orientation of the static GeoPoint with `GeoPointWithOrientation`

```dart
await controller.setStaticPosition(List geoPoints,String id );
```
21) Change/Add Marker old/new static GeoPoint position

> add marker of new static point

> change their marker of existing static geoPoint over time

```dart
await controller.setMarkerOfStaticPoint(String id,MarkerIcon markerIcon );
```

22) change orientation of the map

```dart
await controller.rotateMapCamera(degree);
```

23) Draw Shape in the map

* Circle
```dart
/// to draw
await controller.drawCircle(CircleOSM(
key: "circle0",
centerPoint: GeoPoint(latitude: 47.4333594, longitude: 8.4680184),
radius: 1200.0,
color: Colors.red,
borderColor:Colors.green,
strokeWidth: 0.3,
)
);
/// to remove Circle using Key
await controller.removeCircle("circle0");

/// to remove All Circle in the map
await controller.removeAllCircle();

```
* Rect
```dart
/// to draw
await controller.drawRect(RectOSM(
key: "rect",
centerPoint: GeoPoint(latitude: 47.4333594, longitude: 8.4680184),
distance: 1200.0,
color: Colors.red.withOpacity(0.4),
borderColor:Colors.green,
strokeWidth: 0.3,
));
/// to remove Rect using Key
await controller.removeRect("rect");

/// to remove All Rect in the map
await controller.removeAllRect();

```
* remove all shapes in the map
```dart
await controller.removeAllShapes();
```

### Interfaces:
* OSMMixinObserver :
> contain listener methods to get event from native map view like when mapIsReady,mapRestored

> you should add ths line `controller.addObserver(this);` in initState

> override mapIsReady to implement your own logic after initialisation of the map

> `mapIsReady` will replace `listenerMapIsReady`

| Methods | Description |
| ----------------------------- | ----------------------------------- |
| `mapIsReady` | (callback) Should be override this method, to get notified when map is ready to go or not |
| `mapRestored` | (callback) Should be override this method, to get notified when map is restored you can also add you backup |
| `onSingleTap` | (callback) Called when the user makes single click on map |
| `onLongTap` | (callback) Called when the user makes long click on map |
| `onRegionChanged` | (callback) Notified when map is change region (on moves) |
| `onRoadTap` | (callback) Notified when user click on the polyline (road) |
| `onLocationChanged` | (callback) Notified when user location changed |

** example
```dart
class YourOwnStateWidget extends State with OSMMixinObserver {

//etc
@override
void initState() {
super.initState();
controller.addObserver(this);
}
@override
Future mapIsReady(bool isReady) async {
if (isReady) {
/// put you logic
}
}
@override
Future mapRestored() async {
super.mapRestored();
/// TODO
}
@override
void onSingleTap(GeoPoint position) {
super.onSingleTap();
/// TODO
}

@override
void onLongTap(GeoPoint position) {
super.onLongTap();
/// TODO

}

@override
void onRegionChanged(Region region) {
super.onRegionChanged();
/// TODO
}

@override
void onRoadTap(RoadInfo road) {
super.onRoadTap();
/// TODO
}
@override
void onLocationChanged(GeoPoint userLocation) {
super.onLocationChanged();
/// TODO
}
}
```

## `OSMFlutter`

| Properties | Description |
| ----------------------------- | ----------------------------------- |
| `mapIsLoading` | (Widget) show custom widget when the map finish initialization |
| `osmOption` | (OSMOption) used to configure OSM Map such as zoom,road,userLocationMarker |
| `onGeoPointClicked` | (callback) listener triggered when marker is clicked ,return current geoPoint of the marker |
| `onLocationChanged` | (callback) it is fired when you activate tracking and user position has been changed |
| `onMapMoved` | (callback) it is each the map moved user handler or navigate to another location using APIs |
| `onMapIsReady` | (callback) listener trigger to get map is initialized or not |

## `OSMOption`

| Properties | Description |
| ----------------------------- | ----------------------------------- |
| `mapIsLoading` | (Widget) show custom widget when the map finish initialization |
| `trackMyPosition` | enable tracking user position. |
| `showZoomController` | show default zoom controller. |
| `userLocationMarker` | change user marker or direction marker icon in tracking location |
| `markerOption` | configure marker of osm map |
| `zoomOption` | set configuration for zoom in the Map
| `roadConfiguration` | (RoadOption) set default color,width,borderColor,borderWdith for polylines |
| `staticPoints` | List of Markers you want to show always ,should every marker have unique id |
| `showContributorBadgeForOSM` | (bool) enable to show copyright widget of osm in the map |
| `enableRotationByGesture` | (bool) enable to rotation gesture for map, default: false |
| `showDefaultInfoWindow` | (bool) enable/disable default infoWindow of marker (default = false) |
| `isPicker` | (bool) enable advanced picker from init of the map (default = false) |

## `ZoomOption`

| Properties | Description |
| ----------------------------- | ------------------------------------------------------------ |
| `stepZoom` | set step zoom to use in zoomIn()/zoomOut() (default 1) |
| `initZoom` | set init zoom level in the map (default 10) |
| `maxZoomLevel` | set maximum zoom level in the map (2 <= x <= 19) |
| `minZoomLevel` | set minimum zoom level in the map (2 <= x <= 19 ) |

### Custom Controller
> To create your own MapController to need to extends from `BaseMapController`,
> if you want to make a custom initialization to need to call init() and put your code after super.init()

* example
```dart
class CustomMapController extends BaseMapController {

@override
void dispose() {
/// TODO put you logic here
super.dispose();
}

@override
void init() {
super.init();
/// TODO put you logic here
}
}
```
### STATIC Map:

> using `OSMViewer` we can show static map that contain on location

```dart
OSMViewer(
controller: SimpleMapController(
initPosition: GeoPoint(
latitude: 47.4358055,
longitude: 8.4737324,
),
markerHome: const MarkerIcon(
icon: Icon(Icons.home),
),
),
zoomOption: const ZoomOption(
initZoom: 16,
minZoomLevel: 11,
)

```

## STATIC METHODS:

1) Calculate distance between 2 geoPoint position
```dart
double distanceEnMetres = await distance2point(GeoPoint(longitude: 36.84612143139903,latitude: 11.099388684927824,),
GeoPoint( longitude: 36.8388023164018, latitude: 11.096959785428027, ),);
```

2) Get search Suggestion of text

> you should know that i'm using public api, don't make lot of request

```dart
List suggestions = await addressSuggestion("address");
```

## show dialog picker

> simple dialog location picker to selected user location

```dart
GeoPoint p = await showSimplePickerLocation(
context: context,
isDismissible: true,
title: "Title dialog",
textConfirmPicker: "pick",
initCurrentUserPosition: true,
)
```

## CustomLocationPicker
> customizable widget to build search location

> you should use `PickerMapController` as controller for the widget
see example : [ search widget ](https://github.com/liodali/osm_flutter/blob/master/example/lib/search_example.dart)

#### Properties of `CustomLocationPicker`

| Properties | Description |
| ------------------------ | ----------------------------------- |
| `controller` | (PickerMapController) controller of the widget |
| `appBarPicker` | (AppBar) appbar for the widget |
| `topWidgetPicker` | (Widget?) widget will be show on top of osm map,for example to show address suggestion |
| `bottomWidgetPicker` | (Widget?) widget will be show at bottom of screen for example to show more details about selected location or more action |

## NOTICE:
> `For now the map working for android,iOS , web will be available soon `

> ` If you get ssl certfiction exception,use can use http by following instruction below `

> ` If you want to use http in Android PIE or above : `
* enable useSecureURL and add ` android:usesCleartextTraffic="true" ` in your manifest like example below :

* `
`
> if you faced build error in fresh project you need to follow those instruction [#40](https://github.com/liodali/osm_flutter/issues/40)

1) remove flutter_osm_plugin from pubspec, after that pub get
2) open android module in android studio ( right click in name of project -> flutter-> open android module in android studio)
3) update gradle version to 4.1.1 ( IDE will show popup to make update)
4) update kotlin version to 1.4.21 & re-build the project
5) re-add flutter_osm_plugin in pubspec , pub get ( or flutter clean & pub get )

> Before you publish your application using this library,
> you should take care about copyright of openStreetMap Data,
> that's why i add `CopyrightOSMWidget` see example and this issue [#101](https://github.com/liodali/osm_flutter/issues/101)

#### MIT LICENCE