liodali/osm_flutter
OpenStreetMap plugin for flutter
github へ移動してダウンロード
flutter_osm_plugin
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)
- 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
Installing
Add the following to your pubspec.yaml
file:
dependencies:
flutter_osm_plugin: ^1.0.0
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
:
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 useinitMapWithUserPosition
orinitPosition
if you want the map to initialize using static position use the named constructorwithPosition
or if you want to initialize the map with user position usewithUserPosition
// 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
controller.dispose();
3) Properties of default MapController
MapController
has 2 named ConstructorMapController.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
controller = MapController.customLayer(
initPosition: GeoPoint(
latitude: 47.4358055,
longitude: 8.4737324,
),
customTile: CustomTile(
sourceName: "opentopomap",
tileExtension: ".png",
minZoomLevel: 2,
maxZoomLevel: 19,
urlsServers: [
TileURLs(
url: "https://tile.opentopomap.org/",
subdomains: [],
)
],
tileSize: 256,
),
)
- also,you can use our predefined custom tiles like
cyclOSMLayer
constructor for cycling tilespublicTransportationLayer
constructor for transport tiles ,it’s public osm server
For more example see our example in home_example.dart
3.2) Change Layers in runtime
await controller.changeTileLayer(tileLayer: CustomTile(...));
4) Set map on user current location
await controller.currentLocation();
5) Zoom IN
await controller.setZoom(stepZoom: 2);
// or
await controller.zoomIn();
5.1) Zoom Out
await controller.setZoom(stepZoom: -2);
// or
await controller.zoomOut();
5.2) change zoom level
zoomLevel
should be betweenminZoomLevel
andmaxZoomLevel
await controller.setZoom(zoomLevel: 8);
5.3) zoom to specific bounding box
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>
await controller.getZoom();
7) BoundingBox
set bounding box in the map
await controller.limitAreaMap(BoundingBox( east: 10.4922941, north: 47.8084648, south: 45.817995, west: 5.9559113,));
remove bounding box in the map
await controller.removeLimitAreaMap();
8) Track user current position
for iOS,you should add those line in your info.plist file
<key>NSLocationWhenInUseUsageDescription</key>
<string>any text you want</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>any text you want</string>
from version 0.40.0 we can call only
enableTracking
will animate to user location
without need to callcurrentLocation
when
enableStopFollow
is true,map will not be centered if the user location changed
you can disable rotation of personIcon using [disableUserMarkerRotation] (default: false)
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
await controller.startLocationUpdating();
9) Disable tracking user position
await controller.disabledTracking();
or
use this method below if you already used
startLocationUpdating
await controller.stopLocationUpdating();
10) update the location
Change the location without create marker
await controller.moveTo(GeoPoint(latitude: 47.35387, longitude: 8.43609),animate:true);
11) recuperation current position
GeoPoint geoPoint = await controller.myLocation();
12) get center map
GeoPoint centerMap = await controller.centerMap;
12.1) get geoPoint in the map
- recuperate geoPoint of marker add it by user except static points
List<GeoPoint> geoPoints = await controller.geopoints;
13) get bounding box map
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
controller.listenerMapSingleTapping.addListener(() {
if (controller.listenerMapSingleTapping.value != null) {
/// put you logic here
}
});
a.2) long tap listener
controller.listenerMapLongTapping.addListener(() {
if (controller.listenerMapLongTapping.value != null) {
/// put you logic here
}
});
a.3) region change listener
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
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
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
await controller.setMarkerIcon(GeoPoint,MarkerIcon);
15.3) Remove marker
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
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) |
16.b) draw road manually
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
await controller.removeLastRoad();
18) draw multiple roads
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
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
await controller.setStaticPosition(List<GeoPoint> 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
await controller.setMarkerOfStaticPoint(String id,MarkerIcon markerIcon );
22) change orientation of the map
await controller.rotateMapCamera(degree);
23) Draw Shape in the map
- Circle
/// 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
/// 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
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 replacelistenerMapIsReady
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
class YourOwnStateWidget extends State<YourWidget> with OSMMixinObserver {
//etc
@override
void initState() {
super.initState();
controller.addObserver(this);
}
@override
Future<void> mapIsReady(bool isReady) async {
if (isReady) {
/// put you logic
}
}
@override
Future<void> 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
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 METHODS:
1) Calculate distance between 2 geoPoint position
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
List<SearchInfo> suggestions = await addressSuggestion("address");
show dialog picker
simple dialog location picker to selected user location
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
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 :<application ... android:usesCleartextTraffic="true">
if you faced build error in fresh project you need to follow those instruction #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 addCopyrightOSMWidget
see example and this issue #101
MIT LICENCE
![](/images/banner-woo.jpg)
関連する liodali/osm_flutter 優れたプロジェクトの推薦ダウンロード
AppFlowy
47859
AppFlowy is an open-source alternative to Notion. You are in charge of your data and customizations. Built with Flutter and Rust.
localsend
33797
An open-source cross-platform alternative to AirDrop
spotube
23772
🎧 Open source Spotify client that doesn't require Premium nor uses Electron! Available for both desktop & mobile!
revanced-manager
15035
💊 Application to use ReVanced on Android
gsy_github_app_flutter
14559
Flutter 超完整的开源项目,功能丰富,适合学习和日常使用。GSYGithubApp系列的优势:我们目前已经拥有Flutter、Weex、ReactNative、kotlin 四个版本。 功能齐全,项目框架内技术涉及面广,完成度高,持续维护,配套文章,适合全面学习,对比参考。跨平台的开源Github客户端App,更好的体验,更丰富的功能,旨在更好的日常管理和维护个人Github,提供更好更方便的驾车体验Σ( ̄。 ̄ノ)ノ。同款Weex版本 : https://github.com/CarGuo/GSYGithubAppWeex 、同款React Native版本 : https://github.com/CarGuo/GSYGithubApp 、原生 kotlin 版本 https://github.com/CarGuo/GSYGithubAppKotlin
dio
12249
A powerful HTTP client for Dart and Flutter, which supports global settings, Interceptors, FormData, aborting and canceling a request, files uploading and downloading, requests timeout, custom adapters, etc.
gopeed
11832
A modern download manager that supports all platforms. Built with Golang and Flutter.
bloc
11441
A predictable state management library that helps implement the BLoC design pattern
getx
9899
Open screens/snackbars/dialogs/bottomSheets without context, manage states and inject dependencies easily with Get.
flame
8846
A Flutter based game engine.
flutter_deer
7595
🦌 Flutter 练习项目(包括集成测试、可访问性测试)。内含完整UI设计图,更贴近真实项目的练习。Flutter practice project (including integration testing and accessibility testing). Contains complete UI design drawings for a more realistic practice project.
fish-redux
7343
An assembled flutter application framework.
fl_chart
6451
FL Chart is a highly customizable Flutter chart library that supports Line Chart, Bar Chart, Pie Chart, Scatter Chart, and Radar Chart.
pixez-flutter
6360
一个支持免代理直连及查看动图的第三方Pixiv flutter客户端
Flutter-Responsive-Admin-Panel-or-Dashboard
6355
Responsive Admin Panel or Dashboard using Flutter
aidea
6021
AIdea 是一款支持 GPT 以及国产大语言模型通义千问、文心一言等,支持 Stable Diffusion 文生图、图生图、 SDXL1.0、超分辨率、图片上色的全能型 APP。
riverpod
5828
A reactive caching and data-binding framework. Riverpod makes working with asynchronous code a breeze.
pikapika
5463
美观易用且无广告的漫画和游戏客户端,同时支持MacOS,Windows,Android,iOS。
provider
5029
InheritedWidgets, but simple
getwidget
4416
Most popular and easy to use open source UI library with 1000+ Widgets to build flutter app.