diff --git a/.github/workflows/flutter_ci.yml b/.github/workflows/flutter_ci.yml
index 4168440c2..ef674f5c5 100644
--- a/.github/workflows/flutter_ci.yml
+++ b/.github/workflows/flutter_ci.yml
@@ -7,7 +7,6 @@ jobs:
name: "Static code analysis"
runs-on: ubuntu-latest
-
steps:
- uses: actions/checkout@v1
- uses: actions/setup-java@v1
@@ -16,7 +15,7 @@ jobs:
- uses: subosito/flutter-action@v1
- run: flutter pub get
- name: Lint analysis
- run: flutter analyze
+ run: cd example && flutter analyze
build-android:
name: "Build Android apk"
@@ -29,7 +28,6 @@ jobs:
java-version: '12.x'
- uses: subosito/flutter-action@v1
- run: flutter pub get
-
- name: Build example APK
run: cd example && flutter build apk
# We might want to add a flutter test step in the future, when there actually are tests for this plugin
@@ -37,17 +35,32 @@ jobs:
build-iOS:
name: Build iOS package
runs-on: macos-latest
+
steps:
- uses: actions/checkout@v1
- uses: actions/setup-java@v1
with:
java-version: '12.x'
- uses: subosito/flutter-action@v1
- - name: Upgrade flutter
- run: |
- flutter channel master
- flutter upgrade
+ - run: flutter pub get
- name: build iOS package
run: |
cd ./example
flutter build ios --release --no-codesign
+
+ build-web:
+ name: "Build web"
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v1
+ - uses: actions/setup-java@v1
+ with:
+ java-version: '12.x'
+ - uses: subosito/flutter-action@v1
+ with:
+ channel: beta
+ - run: flutter config --enable-web
+ - run: flutter pub get
+ - name: Build web
+ run: cd example && flutter build web
diff --git a/.gitignore b/.gitignore
index c530f7be0..17c0893ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,114 @@
-android/.classpath
-android/.project
-.packages
-.vscode/
+# Miscellaneous
+*.class
+*.lock
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
.idea/
-android/.settings/org.eclipse.buildship.core.prefs
+# Visual Studio Code related
+.classpath
+.project
+.settings/
+.vscode/
+
+# Flutter repo-specific
+/bin/cache/
+/bin/mingit/
+/dev/benchmarks/mega_gallery/
+/dev/bots/.recipe_deps
+/dev/bots/android_tools/
+/dev/docs/doc/
+/dev/docs/flutter.docs.zip
+/dev/docs/lib/
+/dev/docs/pubspec.yaml
+/dev/integration_tests/**/xcuserdata
+/dev/integration_tests/**/Pods
+/packages/flutter/coverage/
+version
+
+# packages file containing multi-root paths
+.packages.generated
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+build/
+flutter_*.png
+linked_*.ds
+unlinked.ds
+unlinked_spec.ds
+
+# Android related
+**/android/**/gradle-wrapper.jar
+**/android/.gradle
+**/android/captures/
+**/android/gradlew
+**/android/gradlew.bat
+**/android/local.properties
+**/android/**/GeneratedPluginRegistrant.java
+**/android/key.properties
+*.jks
+
+# iOS/XCode related
+**/ios/**/*.mode1v3
+**/ios/**/*.mode2v3
+**/ios/**/*.moved-aside
+**/ios/**/*.pbxuser
+**/ios/**/*.perspectivev3
+**/ios/**/*sync/
+**/ios/**/.sconsign.dblite
+**/ios/**/.tags*
+**/ios/**/.vagrant/
+**/ios/**/DerivedData/
+**/ios/**/Icon?
+**/ios/**/Pods/
+**/ios/**/.symlinks/
+**/ios/**/profile
+**/ios/**/xcuserdata
+**/ios/.generated/
+**/ios/Flutter/App.framework
+**/ios/Flutter/Flutter.framework
+**/ios/Flutter/Flutter.podspec
+**/ios/Flutter/Generated.xcconfig
+**/ios/Flutter/app.flx
+**/ios/Flutter/app.zip
+**/ios/Flutter/flutter_assets/
+**/ios/Flutter/flutter_export_environment.sh
+**/ios/ServiceDefinitions.json
+**/ios/Runner/GeneratedPluginRegistrant.*
+
+# macOS
+**/macos/Flutter/GeneratedPluginRegistrant.swift
+**/macos/Flutter/Flutter-Debug.xcconfig
+**/macos/Flutter/Flutter-Release.xcconfig
+**/macos/Flutter/Flutter-Profile.xcconfig
+
+# Coverage
+coverage/
+
+# Symbols
+app.*.symbols
+
+# Exceptions to above rules.
+!**/ios/**/default.mode1v3
+!**/ios/**/default.mode2v3
+!**/ios/**/default.pbxuser
+!**/ios/**/default.perspectivev3
+!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
+!/dev/ci/**/Gemfile.lock
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8538da84e..df882e874 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,20 @@
+## 0.7.0, June 6, 2020
+* Introduction of mapbox_gl_platform_interface library
+* Introduction of mapbox_gl_web library
+* Integrate web support through mapbox-gl-js
+* Add icon-allow-overlap configurations
+
+## 0.0.6, May 31, 2020
+* Update mapbox depdendency to 9.2.0 (android) and 5.6.0 (iOS)
+* Long press handlers for both iOS as Android
+* Change default location tracking to none
+* OnCameraIdle listener support
+* Add image to style
+* Add animation duration to animateCamera
+* Content insets
+* Visible region support on iOS
+* Numerous bug fixes
+
## 0.0.5, December 21, 2019
* iOS support for annotation extensions (circle, symbol, line)
* Update SDK to 8.5.0 (Android) and 5.5.0 (iOS)
diff --git a/README.md b/README.md
index a723ee01e..08b9ac1d0 100644
--- a/README.md
+++ b/README.md
@@ -1,62 +1,54 @@
-# Flutter Mapbox GL Native
+# Flutter Mapbox GL
> **Please note that this project is community driven and is not an official Mapbox product.** We welcome [feedback](https://github.com/tobrun/flutter-mapbox-gl/issues) and contributions.
-This Flutter plugin for [mapbox-gl-native](https://github.com/mapbox/mapbox-gl-native) enables
-embedded interactive and customizable vector maps inside a Flutter widget by embedding Android and iOS views.
+This Flutter plugin allows to show embedded interactive and customizable vector maps inside a Flutter widget. For the Android and iOS integration, we use [mapbox-gl-native](https://github.com/mapbox/mapbox-gl-native). For web, we rely on [mapbox-gl-js](https://github.com/mapbox/mapbox-gl-js). This project only supports a subset of the API exposed by these libraries.
![screenshot.png](screenshot.png)
-## Install
-This project is available on [pub.dev](https://pub.dev/packages/mapbox_gl), follow the [instructions](https://flutter.dev/docs/development/packages-and-plugins/using-packages#adding-a-package-dependency-to-an-app) to integrate a package into your flutter application.
-
-## :new: :new: Who's using this SDK :new: :new:
-
-We're compiling a list of apps using this SDK. If you want to be listed here, please open a PR and add yourself below (or open a ticket and we'll add you).
-
-- You?
-
-### Running example app
+## Running the example app
- Install [Flutter](https://flutter.io/get-started/) and validate its installation with `flutter doctor`
-- Clone this repository with `git clone git@github.com:mapbox/flutter-mapbox-gl.git`
-- Run the app with `cd flutter_mapbox/example && flutter run`
+- Clone the repository with `git clone git@github.com:tobrun/flutter-mapbox-gl.git`
+- Add a Mapbox access token to the example app (see next section)
+- Connect a mobile device or start an emulator, simulator or chrome
+- Locate the id of a the device with `flutter devices`
+- Run the app with `cd flutter_mapbox/example && flutter packages get && flutter run -d {device_id}`
-#### Mapbox Access Token
+## Adding a Mapbox Access Token
This project uses Mapbox vector tiles, which requires a Mapbox account and a Mapbox access token. Obtain a free access token on [your Mapbox account page](https://www.mapbox.com/account/access-tokens/).
> **Even if you do not use Mapbox vector tiles but vector tiles from a different source (like self-hosted tiles) with this plugin, you will need to specify any non-empty string as Access Token as explained below!**
-##### Android
-Add Mapbox read token value in the application manifest ```android/app/src/main/AndroidManifest.xml:```
-```
-```
+The **recommended** way to provide your access token is through the `MapboxMap` constructor's `accessToken` parameter, which is available starting from the v0.8 release. Note that you should always use the same token throughout your entire app.
-#### iOS
-Add these lines to your Info.plist
+An alternative method to provide access tokens that was required until the v0.7 release is described in [this wiki article](https://github.com/tobrun/flutter-mapbox-gl/wiki/Mapbox-access-tokens).
-```plist
-io.flutter.embedded_views_preview
-
-MGLMapboxAccessToken
-YOUR_TOKEN_HERE
-```
+## Using the SDK in your project
+
+This project is available on [pub.dev](https://pub.dev/packages/mapbox_gl), follow the [instructions](https://flutter.dev/docs/development/packages-and-plugins/using-packages#adding-a-package-dependency-to-an-app) to integrate a package into your flutter application. For platform specific integration, use the flutter application under the example folder as reference.
## Supported API
-| Feature | Android | iOS |
-| ------ | ------ | ----- |
-| Style | :white_check_mark: | :white_check_mark: |
-| Camera | :white_check_mark: | :white_check_mark: |
-| Gesture | :white_check_mark: | :white_check_mark: |
-| User Location | :white_check_mark: | :white_check_mark: |
-| Symbol | :white_check_mark: | :white_check_mark: |
-| Circle | :white_check_mark: | :white_check_mark: |
-| Line | :white_check_mark: | :white_check_mark: |
-| Fill | | |
+| Feature | Android | iOS | Web |
+| ------ | ------ | ----- | ----- |
+| Style | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Camera | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Gesture | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| User Location | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Symbol | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Circle | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Line | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+| Fill | | | |
+
+## Map Styles
+
+Map styles can be supplied by setting the `styleString` in the `MapOptions`. The following formats are supported:
+
+1. Passing the URL of the map style. This can be one of the built-in map styles, also see `MapboxStyles` or a custom map style served remotely using a URL that start with 'http(s)://' or 'mapbox://'
+2. Passing the style as a local asset. Create a JSON file in the `assets` and add a reference in `pubspec.yml`. Set the style string to the relative path for this asset in order to load it into the map.
+3. Passing the raw JSON of the map style. This is only supported on Android.
## Offline Sideloading
@@ -81,6 +73,19 @@ Support for offline maps is available by *"side loading"* the required map tiles
}
```
+## Location features
+
+To enable location features in an iOS application:
+
+If you access your users' location, you should also add the following key to your Info.plist to explain why you need access to their location data:
+
+```xml
+NSLocationWhenInUseUsageDescription
+[Your explanation here]
+```
+
+Mapbox [recommends](https://docs.mapbox.com/help/tutorials/first-steps-ios-sdk/#display-the-users-location) the explanation "Shows your location on the map and helps improve the map".
+
## Documentation
This README file currently houses all of the documentation for this Flutter project. Please visit [mapbox.com/android-docs](https://www.mapbox.com/android-docs/) if you'd like more information about the Mapbox Maps SDK for Android and [mapbox.com/ios-sdk](https://www.mapbox.com/ios-sdk/) for more information about the Mapbox Maps SDK for iOS.
@@ -91,12 +96,7 @@ This README file currently houses all of the documentation for this Flutter proj
- **Have a bug to report?** [Open an issue](https://github.com/tobrun/flutter-mapbox-gl/issues/new). If possible, include a full log and information which shows the issue.
- **Have a feature request?** [Open an issue](https://github.com/tobrun/flutter-mapbox-gl/issues/new). Tell us what the feature should do and why you want the feature.
-## Sample code
-
-[This repository's example library](https://github.com/tobrun/flutter-mapbox-gl/tree/master/example/lib) is currently the best place for you to find reference code for this project.
## Contributing
-We welcome contributions to this repository!
-
-If you're interested in helping build this Mapbox/Flutter integration, please read [the contribution guide](https://github.com/tobrun/flutter-mapbox-gl/blob/master/CONTRIBUTING.md) to learn how to get started.
+We welcome contributions to this repository! If you're interested in helping build this Mapbox/Flutter integration, please read [the contribution guide](https://github.com/tobrun/flutter-mapbox-gl/blob/master/CONTRIBUTING.md) to learn how to get started.
diff --git a/android/build.gradle b/android/build.gradle
index 2454ee42d..40393c18e 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -37,9 +37,9 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
dependencies {
- implementation "com.mapbox.mapboxsdk:mapbox-android-sdk:8.5.0"
- implementation "com.mapbox.mapboxsdk:mapbox-android-plugin-annotation-v8:0.7.0"
- implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-localization-v8:0.11.0'
+ implementation "com.mapbox.mapboxsdk:mapbox-android-sdk:9.2.0"
+ implementation "com.mapbox.mapboxsdk:mapbox-android-plugin-annotation-v9:0.8.0"
+ implementation "com.mapbox.mapboxsdk:mapbox-android-plugin-localization-v9:0.12.0"
}
compileOptions {
sourceCompatibility 1.8
diff --git a/android/src/main/java/com/mapbox/mapboxgl/Convert.java b/android/src/main/java/com/mapbox/mapboxgl/Convert.java
index 85cd80e00..c42b1fecc 100644
--- a/android/src/main/java/com/mapbox/mapboxgl/Convert.java
+++ b/android/src/main/java/com/mapbox/mapboxgl/Convert.java
@@ -374,7 +374,7 @@ static void interpretSymbolOptions(Object o, SymbolOptionsSink sink) {
if (geometry != null) {
sink.setGeometry(toLatLng(geometry));
}
- final Object symbolSortKey = data.get("symbolSortKey");
+ final Object symbolSortKey = data.get("zIndex");
if (symbolSortKey != null) {
sink.setSymbolSortKey(toFloat(symbolSortKey));
}
diff --git a/android/src/main/java/com/mapbox/mapboxgl/LineController.java b/android/src/main/java/com/mapbox/mapboxgl/LineController.java
index 44f9a3980..815401a55 100644
--- a/android/src/main/java/com/mapbox/mapboxgl/LineController.java
+++ b/android/src/main/java/com/mapbox/mapboxgl/LineController.java
@@ -6,6 +6,7 @@
package com.mapbox.mapboxgl;
+import java.util.ArrayList;
import java.util.List;
import android.graphics.PointF;
@@ -87,6 +88,15 @@ public void setGeometry(List geometry) {
line.setLatLngs(geometry);
}
+ public List getGeometry() {
+ List points = line.getGeometry().coordinates();
+ List latLngs = new ArrayList<>();
+ for (Point point : points) {
+ latLngs.add(new LatLng(point.latitude(), point.longitude()));
+ }
+ return latLngs;
+ }
+
@Override
public void setDraggable(boolean draggable) {
line.setDraggable(draggable);
diff --git a/android/src/main/java/com/mapbox/mapboxgl/MapboxMapBuilder.java b/android/src/main/java/com/mapbox/mapboxgl/MapboxMapBuilder.java
index 86001c7fd..d6fc0a6c7 100644
--- a/android/src/main/java/com/mapbox/mapboxgl/MapboxMapBuilder.java
+++ b/android/src/main/java/com/mapbox/mapboxgl/MapboxMapBuilder.java
@@ -31,9 +31,9 @@ class MapboxMapBuilder implements MapboxMapOptionsSink {
private String styleString = Style.MAPBOX_STREETS;
MapboxMapController build(
- int id, Context context, AtomicInteger state, PluginRegistry.Registrar registrar) {
+ int id, Context context, AtomicInteger state, PluginRegistry.Registrar registrar, String accessToken) {
final MapboxMapController controller =
- new MapboxMapController(id, context, state, registrar, options, styleString);
+ new MapboxMapController(id, context, state, registrar, options, accessToken, styleString);
controller.init();
controller.setMyLocationEnabled(myLocationEnabled);
controller.setMyLocationTrackingMode(myLocationTrackingMode);
diff --git a/android/src/main/java/com/mapbox/mapboxgl/MapboxMapController.java b/android/src/main/java/com/mapbox/mapboxgl/MapboxMapController.java
index 53df290d7..ffe1e6d93 100644
--- a/android/src/main/java/com/mapbox/mapboxgl/MapboxMapController.java
+++ b/android/src/main/java/com/mapbox/mapboxgl/MapboxMapController.java
@@ -26,6 +26,9 @@
import androidx.annotation.NonNull;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineCallback;
import com.mapbox.android.core.location.LocationEngineProvider;
@@ -60,6 +63,7 @@
import com.mapbox.mapboxsdk.plugins.annotation.Line;
import com.mapbox.mapboxsdk.plugins.annotation.LineManager;
import com.mapbox.geojson.Feature;
+import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
@@ -90,6 +94,7 @@ final class MapboxMapController
MapboxMap.OnCameraMoveStartedListener,
OnAnnotationClickListener,
MapboxMap.OnMapClickListener,
+ MapboxMap.OnMapLongClickListener,
MapboxMapOptionsSink,
MethodChannel.MethodCallHandler,
com.mapbox.mapboxsdk.maps.OnMapReadyCallback,
@@ -124,6 +129,7 @@ final class MapboxMapController
private LocationComponent locationComponent = null;
private LocationEngine locationEngine = null;
private LocalizationPlugin localizationPlugin;
+ private Style style;
MapboxMapController(
int id,
@@ -131,8 +137,9 @@ final class MapboxMapController
AtomicInteger activityState,
PluginRegistry.Registrar registrar,
MapboxMapOptions options,
+ String accessToken,
String styleStringInitial) {
- Mapbox.getInstance(context, getAccessToken(context));
+ Mapbox.getInstance(context, accessToken!=null ? accessToken : getAccessToken(context));
this.id = id;
this.context = context;
this.activityState = activityState;
@@ -224,17 +231,6 @@ private CameraPosition getCameraPosition() {
return trackCameraPosition ? mapboxMap.getCameraPosition() : null;
}
- private SymbolBuilder newSymbolBuilder() {
- return new SymbolBuilder(symbolManager);
- }
-
- private void removeSymbol(String symbolId) {
- final SymbolController symbolController = symbols.remove(symbolId);
- if (symbolController != null) {
- symbolController.remove(symbolManager);
- }
- }
-
private SymbolController symbol(String symbolId) {
final SymbolController symbol = symbols.get(symbolId);
if (symbol == null) {
@@ -311,6 +307,14 @@ public void setStyleString(String styleString) {
Log.e(TAG, "setStyleString - string empty or null");
} else if (styleString.startsWith("{") || styleString.startsWith("[")) {
mapboxMap.setStyle(new Style.Builder().fromJson(styleString), onStyleLoadedCallback);
+ } else if (
+ !styleString.startsWith("http://") &&
+ !styleString.startsWith("https://")&&
+ !styleString.startsWith("mapbox://")) {
+ // We are assuming that the style will be loaded from an asset here.
+ AssetManager assetManager = registrar.context().getAssets();
+ String key = registrar.lookupKeyForAsset(styleString);
+ mapboxMap.setStyle(new Style.Builder().fromUri("asset://" + key), onStyleLoadedCallback);
} else {
mapboxMap.setStyle(new Style.Builder().fromUrl(styleString), onStyleLoadedCallback);
}
@@ -319,6 +323,7 @@ public void setStyleString(String styleString) {
Style.OnStyleLoaded onStyleLoadedCallback = new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {
+ MapboxMapController.this.style = style;
enableLineManager(style);
enableSymbolManager(style);
enableCircleManager(style);
@@ -328,6 +333,7 @@ public void onStyleLoaded(@NonNull Style style) {
// needs to be placed after SymbolManager#addClickListener,
// is fixed with 0.6.0 of annotations plugin
mapboxMap.addOnMapClickListener(MapboxMapController.this);
+ mapboxMap.addOnMapLongClickListener(MapboxMapController.this);
localizationPlugin = new LocalizationPlugin(mapView, mapboxMap, style);
@@ -369,6 +375,8 @@ private void enableSymbolManager(@NonNull Style style) {
}
}
+
+
private void enableLineManager(@NonNull Style style) {
if (lineManager == null) {
lineManager = new LineManager(mapView, mapboxMap, style);
@@ -459,24 +467,28 @@ public void onCancel() {
}
case "camera#animate": {
final CameraUpdate cameraUpdate = Convert.toCameraUpdate(call.argument("cameraUpdate"), mapboxMap, density);
- if (cameraUpdate != null) {
- // camera transformation not handled yet
- mapboxMap.animateCamera(cameraUpdate, new OnCameraMoveFinishedListener(){
- @Override
- public void onFinish() {
- super.onFinish();
- result.success(true);
- }
+ final Integer duration = call.argument("duration");
- @Override
- public void onCancel() {
- super.onCancel();
- result.success(false);
- }
- });
+ final OnCameraMoveFinishedListener onCameraMoveFinishedListener = new OnCameraMoveFinishedListener(){
+ @Override
+ public void onFinish() {
+ super.onFinish();
+ result.success(true);
+ }
- // animateCamera(cameraUpdate);
- }else {
+ @Override
+ public void onCancel() {
+ super.onCancel();
+ result.success(false);
+ }
+ };
+ if (cameraUpdate != null && duration != null) {
+ // camera transformation not handled yet
+ mapboxMap.animateCamera(cameraUpdate, duration, onCameraMoveFinishedListener);
+ } else if (cameraUpdate != null) {
+ // camera transformation not handled yet
+ mapboxMap.animateCamera(cameraUpdate, onCameraMoveFinishedListener);
+ } else {
result.success(false);
}
break;
@@ -487,9 +499,13 @@ public void onCancel() {
String[] layerIds = ((List) call.argument("layerIds")).toArray(new String[0]);
- String filter = (String) call.argument("filter");
-
- Expression filterExpression = filter == null ? null : new Expression(filter);
+ List filter = call.argument("filter");
+ JsonElement jsonElement = filter == null ? null : new Gson().toJsonTree(filter);
+ JsonArray jsonArray = null;
+ if (jsonElement != null && jsonElement.isJsonArray()) {
+ jsonArray = jsonElement.getAsJsonArray();
+ }
+ Expression filterExpression = jsonArray == null ? null : Expression.Converter.convert(jsonArray);
if (call.hasArgument("x")) {
Double x = call.argument("x");
Double y = call.argument("y");
@@ -538,18 +554,44 @@ public void onError(@NonNull String message) {
});
break;
}
- case "symbol#add": {
- final SymbolBuilder symbolBuilder = newSymbolBuilder();
- Convert.interpretSymbolOptions(call.argument("options"), symbolBuilder);
- final Symbol symbol = symbolBuilder.build();
- final String symbolId = String.valueOf(symbol.getId());
- symbols.put(symbolId, new SymbolController(symbol, true, this));
- result.success(symbolId);
+ case "symbols#addAll": {
+ List newSymbolIds = new ArrayList();
+ final List options = call.argument("options");
+ List symbolOptionsList = new ArrayList();
+ if (options != null) {
+ SymbolBuilder symbolBuilder;
+ for (Object o : options) {
+ symbolBuilder = new SymbolBuilder();
+ Convert.interpretSymbolOptions(o, symbolBuilder);
+ symbolOptionsList.add(symbolBuilder.getSymbolOptions());
+ }
+ if (!symbolOptionsList.isEmpty()) {
+ List newSymbols = symbolManager.create(symbolOptionsList);
+ String symbolId;
+ for (Symbol symbol : newSymbols) {
+ symbolId = String.valueOf(symbol.getId());
+ newSymbolIds.add(symbolId);
+ symbols.put(symbolId, new SymbolController(symbol, true, this));
+ }
+ }
+ }
+ result.success(newSymbolIds);
break;
}
- case "symbol#remove": {
- final String symbolId = call.argument("symbol");
- removeSymbol(symbolId);
+ case "symbols#removeAll": {
+ final ArrayList symbolIds = call.argument("symbols");
+ SymbolController symbolController;
+
+ List symbolList = new ArrayList();
+ for(String symbolId : symbolIds){
+ symbolController = symbols.remove(symbolId);
+ if (symbolController != null) {
+ symbolList.add(symbolController.getSymbol());
+ }
+ }
+ if(!symbolList.isEmpty()) {
+ symbolManager.delete(symbolList);
+ }
result.success(null);
break;
}
@@ -561,6 +603,39 @@ public void onError(@NonNull String message) {
result.success(null);
break;
}
+ case "symbol#getGeometry": {
+ final String symbolId = call.argument("symbol");
+ final SymbolController symbol = symbol(symbolId);
+ final LatLng symbolLatLng = symbol.getGeometry();
+ Map hashMapLatLng = new HashMap<>();
+ hashMapLatLng.put("latitude", symbolLatLng.getLatitude());
+ hashMapLatLng.put("longitude", symbolLatLng.getLongitude());
+ result.success(hashMapLatLng);
+ }
+ case "symbolManager#iconAllowOverlap": {
+ final Boolean value = call.argument("iconAllowOverlap");
+ symbolManager.setIconAllowOverlap(value);
+ result.success(null);
+ break;
+ }
+ case "symbolManager#iconIgnorePlacement": {
+ final Boolean value = call.argument("iconIgnorePlacement");
+ symbolManager.setIconIgnorePlacement(value);
+ result.success(null);
+ break;
+ }
+ case "symbolManager#textAllowOverlap": {
+ final Boolean value = call.argument("textAllowOverlap");
+ symbolManager.setTextAllowOverlap(value);
+ result.success(null);
+ break;
+ }
+ case "symbolManager#textIgnorePlacement": {
+ final Boolean iconAllowOverlap = call.argument("textIgnorePlacement");
+ symbolManager.setTextIgnorePlacement(iconAllowOverlap);
+ result.success(null);
+ break;
+ }
case "line#add": {
final LineBuilder lineBuilder = newLineBuilder();
Convert.interpretLineOptions(call.argument("options"), lineBuilder);
@@ -584,6 +659,20 @@ public void onError(@NonNull String message) {
result.success(null);
break;
}
+ case "line#getGeometry": {
+ final String lineId = call.argument("line");
+ final LineController line = line(lineId);
+ final List lineLatLngs = line.getGeometry();
+ final List resultList = new ArrayList<>();
+ for (LatLng latLng: lineLatLngs){
+ Map hashMapLatLng = new HashMap<>();
+ hashMapLatLng.put("latitude", latLng.getLatitude());
+ hashMapLatLng.put("longitude", latLng.getLongitude());
+ resultList.add(hashMapLatLng);
+ }
+ result.success(resultList);
+ break;
+ }
case "circle#add": {
final CircleBuilder circleBuilder = newCircleBuilder();
Convert.interpretCircleOptions(call.argument("options"), circleBuilder);
@@ -644,6 +733,14 @@ public void onFailure(@NonNull Exception exception) {
}
break;
}
+ case "style#addImage":{
+ if(style==null){
+ result.error("STYLE IS NULL", "The style is null. Has onStyleLoaded() already been invoked?", null);
+ }
+ style.addImage(call.argument("name"), BitmapFactory.decodeByteArray(call.argument("bytes"),0,call.argument("length")), call.argument("sdf"));
+ result.success(null);
+ break;
+ }
default:
result.notImplemented();
}
@@ -742,6 +839,18 @@ public boolean onMapClick(@NonNull LatLng point) {
return true;
}
+ @Override
+ public boolean onMapLongClick(@NonNull LatLng point) {
+ PointF pointf = mapboxMap.getProjection().toScreenLocation(point);
+ final Map arguments = new HashMap<>(5);
+ arguments.put("x", pointf.x);
+ arguments.put("y", pointf.y);
+ arguments.put("lng", point.getLongitude());
+ arguments.put("lat", point.getLatitude());
+ methodChannel.invokeMethod("map#onMapLongClick", arguments);
+ return true;
+ }
+
@Override
public void dispose() {
if (disposed) {
diff --git a/android/src/main/java/com/mapbox/mapboxgl/MapboxMapFactory.java b/android/src/main/java/com/mapbox/mapboxgl/MapboxMapFactory.java
index bc8299eca..532e53adc 100644
--- a/android/src/main/java/com/mapbox/mapboxgl/MapboxMapFactory.java
+++ b/android/src/main/java/com/mapbox/mapboxgl/MapboxMapFactory.java
@@ -34,6 +34,6 @@ public PlatformView create(Context context, int id, Object args) {
CameraPosition position = Convert.toCameraPosition(params.get("initialCameraPosition"));
builder.setInitialCameraPosition(position);
}
- return builder.build(id, context, mActivityState, mPluginRegistrar);
+ return builder.build(id, context, mActivityState, mPluginRegistrar, (String) params.get("accessToken"));
}
}
diff --git a/android/src/main/java/com/mapbox/mapboxgl/SymbolBuilder.java b/android/src/main/java/com/mapbox/mapboxgl/SymbolBuilder.java
index d0c4cf01b..5f0583138 100644
--- a/android/src/main/java/com/mapbox/mapboxgl/SymbolBuilder.java
+++ b/android/src/main/java/com/mapbox/mapboxgl/SymbolBuilder.java
@@ -13,17 +13,15 @@
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions;
class SymbolBuilder implements SymbolOptionsSink {
- private final SymbolManager symbolManager;
private final SymbolOptions symbolOptions;
private static boolean customImage;
- SymbolBuilder(SymbolManager symbolManager) {
- this.symbolManager = symbolManager;
+ SymbolBuilder() {
this.symbolOptions = new SymbolOptions();
}
- Symbol build() {
- return symbolManager.create(symbolOptions);
+ public SymbolOptions getSymbolOptions(){
+ return this.symbolOptions;
}
@Override
diff --git a/android/src/main/java/com/mapbox/mapboxgl/SymbolController.java b/android/src/main/java/com/mapbox/mapboxgl/SymbolController.java
index b3c95a4c9..bd101032f 100644
--- a/android/src/main/java/com/mapbox/mapboxgl/SymbolController.java
+++ b/android/src/main/java/com/mapbox/mapboxgl/SymbolController.java
@@ -34,6 +34,10 @@ boolean onTap() {
return consumeTapEvents;
}
+ public Symbol getSymbol(){
+ return this.symbol;
+ }
+
void remove(SymbolManager symbolManager) {
symbolManager.delete(symbol);
}
@@ -168,6 +172,11 @@ public void setGeometry(LatLng geometry) {
symbol.setGeometry(Point.fromLngLat(geometry.getLongitude(), geometry.getLatitude()));
}
+ public LatLng getGeometry() {
+ Point point = symbol.getGeometry();
+ return new LatLng(point.latitude(), point.longitude());
+ }
+
@Override
public void setDraggable(boolean draggable) {
symbol.setDraggable(draggable);
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index b819886fb..a337bd737 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -17,7 +17,6 @@
android:name="io.flutter.app.FlutterApplication"
android:label="mapbox_gl_example"
android:icon="@mipmap/ic_launcher">
-
-
- ADD_MAPBOX_ACCESS_TOKEN_HERE
-
diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 000000000..f11e4c8d0
--- /dev/null
+++ b/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/example/android/build.gradle b/example/android/build.gradle
index bb8a30389..e0d7ae2c1 100644
--- a/example/android/build.gradle
+++ b/example/android/build.gradle
@@ -5,7 +5,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.2.1'
+ classpath 'com.android.tools.build:gradle:3.5.0'
}
}
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
index 53ae0ae47..b6e61b62b 100644
--- a/example/android/gradle.properties
+++ b/example/android/gradle.properties
@@ -1,3 +1,4 @@
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M
+android.enableR8=true
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
index 2819f022f..c8f6d36d0 100644
--- a/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Jun 23 08:50:38 CEST 2017
+#Mon May 25 15:33:34 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/example/android/settings_aar.gradle b/example/android/settings_aar.gradle
new file mode 100644
index 000000000..e7b4def49
--- /dev/null
+++ b/example/android/settings_aar.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/example/assets/style.json b/example/assets/style.json
new file mode 100644
index 000000000..f16c075f6
--- /dev/null
+++ b/example/assets/style.json
@@ -0,0 +1,36 @@
+{
+ "version": 8,
+ "name": "Example taken from https://docs.mapbox.com/ios/maps/examples/source-custom-vector/",
+ "sources": {
+ "mapillary": {
+ "type": "vector",
+ "tiles": [
+ "https://d25uarhxywzl1j.cloudfront.net/v0.1/{z}/{x}/{y}.mvt"
+ ],
+ "attribution": "© Mapillary, CC BY ",
+ "maxzoom": 14
+ }
+ },
+ "layers": [{
+ "id": "background",
+ "type": "background",
+ "paint": {
+ "background-color": "#485E77"
+ }
+ },
+ {
+ "id": "mapillary-sequences",
+ "type": "line",
+ "source": "mapillary",
+ "source-layer": "mapillary-sequences",
+ "filter": [
+ "==",
+ "$type",
+ "LineString"
+ ],
+ "paint": {
+ "line-color": "#F56745"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/example/ios/.gitignore b/example/ios/.gitignore
new file mode 100644
index 000000000..e96ef602b
--- /dev/null
+++ b/example/ios/.gitignore
@@ -0,0 +1,32 @@
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index c53701713..4b3022495 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -10,10 +10,6 @@
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
1C318FD9FE81A3CF826CB6E0 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9C618A260D4CE68F2F89632 /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
- 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
- 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
- 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
- 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
@@ -28,8 +24,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
- 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
- 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -41,7 +35,6 @@
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
33EB4B753D90FC406A268B9A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
- 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
647A9CC8EAD456F68D57F590 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
77F62DAA39FA47F19A7FF5D8 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
@@ -49,7 +42,6 @@
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
- 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
@@ -64,8 +56,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
- 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
1C318FD9FE81A3CF826CB6E0 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -84,9 +74,7 @@
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
- 3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
- 9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
@@ -232,7 +220,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
61A6A5795B0A22D55417D672 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
@@ -262,9 +250,12 @@
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${PODS_ROOT}/Mapbox-iOS-SDK/dynamic/Mapbox.framework",
"${PODS_ROOT}/Mapbox-iOS-SDK/dynamic/Mapbox.framework.dSYM",
- "${PODS_ROOT}/Mapbox-iOS-SDK/dynamic/F6FDF133-0198-394E-9C8F-5043F94B4790.bcsymbolmap",
- "${PODS_ROOT}/Mapbox-iOS-SDK/dynamic/B4615DAE-86F8-35AB-B4D1-B1F1420E374A.bcsymbolmap",
+ "${PODS_ROOT}/Mapbox-iOS-SDK/dynamic/4794199C-B164-3A2D-A3B4-553B7D49EDD5.bcsymbolmap",
+ "${PODS_ROOT}/Mapbox-iOS-SDK/dynamic/097AD13C-9FDA-310F-8B76-64CB67B06A27.bcsymbolmap",
+ "${PODS_ROOT}/Mapbox-iOS-SDK/dynamic/491A77E9-7DBC-3309-A93C-BADAE0DDBC6E.bcsymbolmap",
+ "${PODS_ROOT}/Mapbox-iOS-SDK/dynamic/3F114CA8-302D-327F-87C3-670E0EC63C9A.bcsymbolmap",
"${BUILT_PRODUCTS_DIR}/MapboxAnnotationExtension/MapboxAnnotationExtension.framework",
+ "${BUILT_PRODUCTS_DIR}/MapboxMobileEvents/MapboxMobileEvents.framework",
"${BUILT_PRODUCTS_DIR}/location/location.framework",
"${BUILT_PRODUCTS_DIR}/mapbox_gl/mapbox_gl.framework",
);
@@ -273,9 +264,12 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Mapbox.framework",
"${DWARF_DSYM_FOLDER_PATH}/Mapbox.framework.dSYM",
- "${BUILT_PRODUCTS_DIR}/F6FDF133-0198-394E-9C8F-5043F94B4790.bcsymbolmap",
- "${BUILT_PRODUCTS_DIR}/B4615DAE-86F8-35AB-B4D1-B1F1420E374A.bcsymbolmap",
+ "${BUILT_PRODUCTS_DIR}/4794199C-B164-3A2D-A3B4-553B7D49EDD5.bcsymbolmap",
+ "${BUILT_PRODUCTS_DIR}/097AD13C-9FDA-310F-8B76-64CB67B06A27.bcsymbolmap",
+ "${BUILT_PRODUCTS_DIR}/491A77E9-7DBC-3309-A93C-BADAE0DDBC6E.bcsymbolmap",
+ "${BUILT_PRODUCTS_DIR}/3F114CA8-302D-327F-87C3-670E0EC63C9A.bcsymbolmap",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MapboxAnnotationExtension.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MapboxMobileEvents.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/location.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/mapbox_gl.framework",
);
@@ -335,7 +329,6 @@
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -409,7 +402,6 @@
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
@@ -465,7 +457,6 @@
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000..18d981003
--- /dev/null
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
similarity index 77%
rename from example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
rename to example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
index 949b67898..f9b0d7c5e 100644
--- a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -2,7 +2,7 @@
- BuildSystemType
- Original
+ PreviewsEnabled
+
diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift
new file mode 100644
index 000000000..70693e4a8
--- /dev/null
+++ b/example/ios/Runner/AppDelegate.swift
@@ -0,0 +1,13 @@
+import UIKit
+import Flutter
+
+@UIApplicationMain
+@objc class AppDelegate: FlutterAppDelegate {
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+}
diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist
index 76be30434..5ef0ea0b3 100644
--- a/example/ios/Runner/Info.plist
+++ b/example/ios/Runner/Info.plist
@@ -43,13 +43,11 @@
io.flutter.embedded_views_preview
- MGLMapboxAccessToken
- YOUR_TOKEN_HERE
MGLMapboxMetricsEnabledSettingShownInApp
NSLocationWhenInUseUsageDescription
-
+ Shows your location on the map and helps improve the map
NSLocationAlwaysUsageDescription
-
+ Shows your location on the map and helps improve the map
diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h
new file mode 100644
index 000000000..308a2a560
--- /dev/null
+++ b/example/ios/Runner/Runner-Bridging-Header.h
@@ -0,0 +1 @@
+#import "GeneratedPluginRegistrant.h"
diff --git a/example/lib/animate_camera.dart b/example/lib/animate_camera.dart
index 1ab45d28d..b0cdf4c5b 100644
--- a/example/lib/animate_camera.dart
+++ b/example/lib/animate_camera.dart
@@ -5,9 +5,10 @@
import 'package:flutter/material.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
+import 'main.dart';
import 'page.dart';
-class AnimateCameraPage extends Page {
+class AnimateCameraPage extends ExamplePage {
AnimateCameraPage()
: super(const Icon(Icons.map), 'Camera control, animated');
@@ -41,6 +42,7 @@ class AnimateCameraState extends State {
width: 300.0,
height: 200.0,
child: MapboxMap(
+ accessToken: MapsDemo.ACCESS_TOKEN,
onMapCreated: _onMapCreated,
initialCameraPosition:
const CameraPosition(target: LatLng(0.0, 0.0)),
diff --git a/example/lib/full_map.dart b/example/lib/full_map.dart
index ee9b42950..f1bf6a7be 100644
--- a/example/lib/full_map.dart
+++ b/example/lib/full_map.dart
@@ -1,9 +1,10 @@
import 'package:flutter/material.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
+import 'main.dart';
import 'page.dart';
-class FullMapPage extends Page {
+class FullMapPage extends ExamplePage {
FullMapPage()
: super(const Icon(Icons.map), 'Full screen map');
@@ -31,6 +32,7 @@ class FullMapState extends State {
Widget build(BuildContext context) {
return new Scaffold(
body: MapboxMap(
+ accessToken: MapsDemo.ACCESS_TOKEN,
onMapCreated: _onMapCreated,
initialCameraPosition:
const CameraPosition(target: LatLng(0.0, 0.0)),
diff --git a/example/lib/generated_plugin_registrant.dart b/example/lib/generated_plugin_registrant.dart
new file mode 100644
index 000000000..6f912e320
--- /dev/null
+++ b/example/lib/generated_plugin_registrant.dart
@@ -0,0 +1,16 @@
+//
+// Generated file. Do not edit.
+//
+
+// ignore: unused_import
+import 'dart:ui';
+
+import 'package:mapbox_gl_web/mapbox_gl_web.dart';
+
+import 'package:flutter_web_plugins/flutter_web_plugins.dart';
+
+// ignore: public_member_api_docs
+void registerPlugins(PluginRegistry registry) {
+ MapboxMapPlugin.registerWith(registry.registrarFor(MapboxMapPlugin));
+ registry.registerMessageHandler();
+}
diff --git a/example/lib/line.dart b/example/lib/line.dart
index 7dc27adb8..f7f5d9709 100644
--- a/example/lib/line.dart
+++ b/example/lib/line.dart
@@ -7,9 +7,10 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
+import 'main.dart';
import 'page.dart';
-class LinePage extends Page {
+class LinePage extends ExamplePage {
LinePage() : super(const Icon(Icons.share), 'Line');
@override
@@ -79,6 +80,7 @@ class LineBodyState extends State {
lineColor: "#ff0000",
lineWidth: 14.0,
lineOpacity: 0.5,
+ draggable: true
),
);
setState(() {
@@ -143,6 +145,7 @@ class LineBodyState extends State {
width: 300.0,
height: 200.0,
child: MapboxMap(
+ accessToken: MapsDemo.ACCESS_TOKEN,
onMapCreated: _onMapCreated,
onStyleLoadedCallback: onStyleLoadedCallback,
initialCameraPosition: const CameraPosition(
@@ -183,6 +186,16 @@ class LineBodyState extends State {
onPressed:
(_selectedLine == null) ? null : _toggleVisible,
),
+ FlatButton(
+ child: const Text('print current LatLng'),
+ onPressed:
+ (_selectedLine == null) ? null : () async{
+ var latLngs = await controller.getLineLatLngs(_selectedLine);
+ for (var latLng in latLngs) {
+ print(latLng.toString());
+ }
+ },
+ ),
],
),
],
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 4fec3b987..081c97712 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:mapbox_gl_example/full_map.dart';
@@ -16,7 +17,7 @@ import 'place_circle.dart';
import 'place_symbol.dart';
import 'scrolling_map.dart';
-final List _allPages = [
+final List _allPages = [
MapUiPage(),
FullMapPage(),
AnimateCameraPage(),
@@ -28,13 +29,18 @@ final List _allPages = [
];
class MapsDemo extends StatelessWidget {
- void _pushPage(BuildContext context, Page page) async {
- final location = Location();
- final hasPermissions = await location.hasPermission();
- if (!hasPermissions) {
- await location.requestPermission();
- }
+ //FIXME: Add your Mapbox access token here
+ static const String ACCESS_TOKEN = "YOUR_TOKEN_HERE";
+
+ void _pushPage(BuildContext context, ExamplePage page) async {
+ if (!kIsWeb) {
+ final location = Location();
+ final hasPermissions = await location.hasPermission();
+ if (hasPermissions != PermissionStatus.GRANTED) {
+ await location.requestPermission();
+ }
+ }
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => Scaffold(
appBar: AppBar(title: Text(page.title)),
diff --git a/example/lib/map_ui.dart b/example/lib/map_ui.dart
index b86df1d66..6e344495b 100644
--- a/example/lib/map_ui.dart
+++ b/example/lib/map_ui.dart
@@ -5,6 +5,7 @@
import 'package:flutter/material.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
+import 'main.dart';
import 'page.dart';
final LatLngBounds sydneyBounds = LatLngBounds(
@@ -12,7 +13,7 @@ final LatLngBounds sydneyBounds = LatLngBounds(
northeast: const LatLng(-33.571835, 151.325952),
);
-class MapUiPage extends Page {
+class MapUiPage extends ExamplePage {
MapUiPage() : super(const Icon(Icons.map), 'User interface');
@override
@@ -42,7 +43,11 @@ class MapUiBodyState extends State {
bool _compassEnabled = true;
CameraTargetBounds _cameraTargetBounds = CameraTargetBounds.unbounded;
MinMaxZoomPreference _minMaxZoomPreference = MinMaxZoomPreference.unbounded;
- String _styleString = MapboxStyles.MAPBOX_STREETS;
+ int _styleStringIndex = 0;
+ // Style string can a reference to a local or remote resources.
+ // On Android the raw JSON can also be passed via a styleString, on iOS this is not supported.
+ List _styleStrings = [MapboxStyles.MAPBOX_STREETS, MapboxStyles.SATELLITE, "assets/style.json"];
+ List _styleStringLabels = ["MAPBOX_STREETS", "SATELLITE", "LOCAL_ASSET"];
bool _rotateGesturesEnabled = true;
bool _scrollGesturesEnabled = true;
bool _tiltGesturesEnabled = true;
@@ -50,6 +55,7 @@ class MapUiBodyState extends State {
bool _myLocationEnabled = true;
bool _telemetryEnabled = true;
MyLocationTrackingMode _myLocationTrackingMode = MyLocationTrackingMode.Tracking;
+ List _featureQueryFilter;
@override
void initState() {
@@ -86,6 +92,21 @@ class MapUiBodyState extends State {
);
}
+ Widget _queryFilterToggler() {
+ return FlatButton(
+ child: Text('filter zoo on click ${ _featureQueryFilter == null ? 'disabled' : 'enabled'}'),
+ onPressed: () {
+ setState(() {
+ if (_featureQueryFilter == null) {
+ _featureQueryFilter = ["==", ["get", "type"] , "zoo"];
+ } else {
+ _featureQueryFilter = null;
+ }
+ });
+ },
+ );
+ }
+
Widget _compassToggler() {
return FlatButton(
child: Text('${_compassEnabled ? 'disable' : 'enable'} compasss'),
@@ -131,10 +152,10 @@ class MapUiBodyState extends State {
Widget _setStyleToSatellite() {
return FlatButton(
- child: Text('change map style to Satellite'),
+ child: Text('change map style to ${_styleStringLabels[(_styleStringIndex + 1) % _styleStringLabels.length]}'),
onPressed: () {
setState(() {
- _styleString = MapboxStyles.SATELLITE;
+ _styleStringIndex = (_styleStringIndex + 1) % _styleStrings.length;
});
},
);
@@ -220,13 +241,14 @@ class MapUiBodyState extends State {
@override
Widget build(BuildContext context) {
final MapboxMap mapboxMap = MapboxMap(
+ accessToken: MapsDemo.ACCESS_TOKEN,
onMapCreated: onMapCreated,
initialCameraPosition: _kInitialPosition,
trackCameraPosition: true,
compassEnabled: _compassEnabled,
cameraTargetBounds: _cameraTargetBounds,
minMaxZoomPreference: _minMaxZoomPreference,
- styleString: _styleString,
+ styleString: _styleStrings[_styleStringIndex],
rotateGesturesEnabled: _rotateGesturesEnabled,
scrollGesturesEnabled: _scrollGesturesEnabled,
tiltGesturesEnabled: _tiltGesturesEnabled,
@@ -235,8 +257,16 @@ class MapUiBodyState extends State {
myLocationTrackingMode: _myLocationTrackingMode,
myLocationRenderMode: MyLocationRenderMode.GPS,
onMapClick: (point, latLng) async {
- print("${point.x},${point.y} ${latLng.latitude}/${latLng.longitude}");
- List features = await mapController.queryRenderedFeatures(point, [],null);
+ print("Map click: ${point.x},${point.y} ${latLng.latitude}/${latLng.longitude}");
+ print("Filter $_featureQueryFilter");
+ List features = await mapController.queryRenderedFeatures(point, [], _featureQueryFilter);
+ if (features.length>0) {
+ print(features[0]);
+ }
+ },
+ onMapLongClick: (point, latLng) async {
+ print("Map long press: ${point.x},${point.y} ${latLng.latitude}/${latLng.longitude}");
+ List features = await mapController.queryRenderedFeatures(point, [], null);
if (features.length>0) {
print(features[0]);
}
@@ -273,6 +303,7 @@ class MapUiBodyState extends State {
Text('camera zoom: ${_position.zoom}'),
Text('camera tilt: ${_position.tilt}'),
Text(_isMoving ? '(Camera moving)' : '(Camera idle)'),
+ _queryFilterToggler(),
_compassToggler(),
_myLocationTrackingModeCycler(),
_latLngBoundsToggler(),
diff --git a/example/lib/move_camera.dart b/example/lib/move_camera.dart
index ea42b022e..3805b0200 100644
--- a/example/lib/move_camera.dart
+++ b/example/lib/move_camera.dart
@@ -5,9 +5,10 @@
import 'package:flutter/material.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
+import 'main.dart';
import 'page.dart';
-class MoveCameraPage extends Page {
+class MoveCameraPage extends ExamplePage {
MoveCameraPage() : super(const Icon(Icons.map), 'Camera control');
@override
@@ -40,7 +41,9 @@ class MoveCameraState extends State {
width: 300.0,
height: 200.0,
child: MapboxMap(
+ accessToken: MapsDemo.ACCESS_TOKEN,
onMapCreated: _onMapCreated,
+ onCameraIdle: ()=>print("onCameraIdle"),
initialCameraPosition:
const CameraPosition(target: LatLng(0.0, 0.0)),
),
diff --git a/example/lib/page.dart b/example/lib/page.dart
index c9f834b77..ab895ac4e 100644
--- a/example/lib/page.dart
+++ b/example/lib/page.dart
@@ -4,8 +4,8 @@
import 'package:flutter/material.dart';
-abstract class Page extends StatelessWidget {
- const Page(this.leading, this.title);
+abstract class ExamplePage extends StatelessWidget {
+ const ExamplePage(this.leading, this.title);
final Widget leading;
final String title;
diff --git a/example/lib/place_circle.dart b/example/lib/place_circle.dart
index e596ba45f..bc4a17541 100644
--- a/example/lib/place_circle.dart
+++ b/example/lib/place_circle.dart
@@ -8,9 +8,10 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
+import 'main.dart';
import 'page.dart';
-class PlaceCirclePage extends Page {
+class PlaceCirclePage extends ExamplePage {
PlaceCirclePage() : super(const Icon(Icons.check_circle), 'Place circle');
@override
@@ -217,6 +218,7 @@ class PlaceCircleBodyState extends State {
width: 300.0,
height: 200.0,
child: MapboxMap(
+ accessToken: MapsDemo.ACCESS_TOKEN,
onMapCreated: _onMapCreated,
initialCameraPosition: const CameraPosition(
target: LatLng(-33.852, 151.211),
diff --git a/example/lib/place_symbol.dart b/example/lib/place_symbol.dart
index 3e06d31ff..6ec86719b 100644
--- a/example/lib/place_symbol.dart
+++ b/example/lib/place_symbol.dart
@@ -4,13 +4,17 @@
import 'dart:async';
import 'dart:math';
+import 'dart:typed_data';
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:http/http.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
+import 'main.dart';
import 'page.dart';
-class PlaceSymbolPage extends Page {
+class PlaceSymbolPage extends ExamplePage {
PlaceSymbolPage() : super(const Icon(Icons.place), 'Place symbol');
@override
@@ -34,18 +38,37 @@ class PlaceSymbolBodyState extends State {
MapboxMapController controller;
int _symbolCount = 0;
Symbol _selectedSymbol;
+ bool _iconAllowOverlap = false;
void _onMapCreated(MapboxMapController controller) {
this.controller = controller;
controller.onSymbolTapped.add(_onSymbolTapped);
}
+ void _onStyleLoaded() {
+ addImageFromAsset("assetImage", "assets/symbols/custom-icon.png");
+ addImageFromUrl("networkImage", "https://via.placeholder.com/50");
+ }
+
@override
void dispose() {
controller?.onSymbolTapped?.remove(_onSymbolTapped);
super.dispose();
}
+ /// Adds an asset image to the currently displayed style
+ Future addImageFromAsset(String name, String assetName) async {
+ final ByteData bytes = await rootBundle.load(assetName);
+ final Uint8List list = bytes.buffer.asUint8List();
+ return controller.addImage(name, list);
+ }
+
+ /// Adds a network image to the currently displayed style
+ Future addImageFromUrl(String name, String url) async {
+ var response = await get(url);
+ return controller.addImage(name, response.bodyBytes);
+ }
+
void _onSymbolTapped(Symbol symbol) {
if (_selectedSymbol != null) {
_updateSelectedSymbol(
@@ -67,18 +90,50 @@ class PlaceSymbolBodyState extends State {
}
void _add(String iconImage) {
- controller.addSymbol(
- SymbolOptions(
- geometry: LatLng(
- center.latitude + sin(_symbolCount * pi / 6.0) / 20.0,
- center.longitude + cos(_symbolCount * pi / 6.0) / 20.0,
- ),
- iconImage: iconImage,
+ List availableNumbers = Iterable.generate(12).toList();
+ controller.symbols.forEach(
+ (s) => availableNumbers.removeWhere((i) => i == s.data['count'])
+ );
+ if (availableNumbers.isNotEmpty) {
+ controller.addSymbol(
+ _getSymbolOptions(iconImage, availableNumbers.first),
+ {'count': availableNumbers.first}
+ );
+ setState(() {
+ _symbolCount += 1;
+ });
+ }
+ }
+
+ SymbolOptions _getSymbolOptions(String iconImage, int symbolCount){
+ return SymbolOptions(
+ geometry: LatLng(
+ center.latitude + sin(symbolCount * pi / 6.0) / 20.0,
+ center.longitude + cos(symbolCount * pi / 6.0) / 20.0,
),
+ iconImage: iconImage,
);
- setState(() {
- _symbolCount += 1;
- });
+ }
+
+ Future _addAll(String iconImage) async {
+ List symbolsToAddNumbers = Iterable.generate(12).toList();
+ controller.symbols.forEach(
+ (s) => symbolsToAddNumbers.removeWhere((i) => i == s.data['count'])
+ );
+
+ if (symbolsToAddNumbers.isNotEmpty) {
+ final List symbolOptionsList = symbolsToAddNumbers.map(
+ (i) => _getSymbolOptions(iconImage, i)
+ ).toList();
+ controller.addSymbols(
+ symbolOptionsList,
+ symbolsToAddNumbers.map((i) => {'count': i}).toList()
+ );
+
+ setState(() {
+ _symbolCount += symbolOptionsList.length;
+ });
+ }
}
void _remove() {
@@ -89,6 +144,14 @@ class PlaceSymbolBodyState extends State {
});
}
+ void _removeAll() {
+ controller.removeSymbols(controller.symbols);
+ setState(() {
+ _selectedSymbol = null;
+ _symbolCount = 0;
+ });
+ }
+
void _changePosition() {
final LatLng current = _selectedSymbol.options.geometry;
final Offset offset = Offset(
@@ -185,6 +248,22 @@ class PlaceSymbolBodyState extends State {
);
}
+ void _getLatLng() async {
+ LatLng latLng = await controller.getSymbolLatLng(_selectedSymbol);
+ Scaffold.of(context).showSnackBar(
+ SnackBar(
+ content: Text(latLng.toString()),
+ ),
+ );
+ }
+
+ Future _changeIconOverlap() async {
+ setState(() {
+ _iconAllowOverlap = !_iconAllowOverlap;
+ });
+ controller.setSymbolIconAllowOverlap(_iconAllowOverlap);
+ }
+
@override
Widget build(BuildContext context) {
return Column(
@@ -196,7 +275,9 @@ class PlaceSymbolBodyState extends State {
width: 300.0,
height: 200.0,
child: MapboxMap(
+ accessToken: MapsDemo.ACCESS_TOKEN,
onMapCreated: _onMapCreated,
+ onStyleLoadedCallback: _onStyleLoaded,
initialCameraPosition: const CameraPosition(
target: LatLng(-33.852, 151.211),
zoom: 11.0,
@@ -218,6 +299,11 @@ class PlaceSymbolBodyState extends State {
onPressed: () =>
(_symbolCount == 12) ? null : _add("airport-15"),
),
+ FlatButton(
+ child: const Text('add all'),
+ onPressed: () =>
+ (_symbolCount == 12) ? null : _addAll("airport-15"),
+ ),
FlatButton(
child: const Text('add (custom icon)'),
onPressed: () => (_symbolCount == 12)
@@ -228,6 +314,26 @@ class PlaceSymbolBodyState extends State {
child: const Text('remove'),
onPressed: (_selectedSymbol == null) ? null : _remove,
),
+ FlatButton(
+ child: Text('${_iconAllowOverlap ? 'disable' : 'enable'} icon overlap'),
+ onPressed: _changeIconOverlap,
+ ),
+ FlatButton(
+ child: const Text('remove all'),
+ onPressed: (_symbolCount == 0) ? null : _removeAll,
+ ),
+ FlatButton(
+ child: const Text('add (asset image)'),
+ onPressed: () => (_symbolCount == 12)
+ ? null
+ : _add(
+ "assetImage"), //assetImage added to the style in _onStyleLoaded
+ ),
+ FlatButton(
+ child: const Text('add (network image)'),
+ onPressed: () =>
+ (_symbolCount == 12) ? null : _add("networkImage"), //networkImage added to the style in _onStyleLoaded
+ ),
],
),
Column(
@@ -239,8 +345,9 @@ class PlaceSymbolBodyState extends State {
),
FlatButton(
child: const Text('change icon offset'),
- onPressed:
- (_selectedSymbol == null) ? null : _changeIconOffset,
+ onPressed: (_selectedSymbol == null)
+ ? null
+ : _changeIconOffset,
),
FlatButton(
child: const Text('change icon anchor'),
@@ -276,6 +383,12 @@ class PlaceSymbolBodyState extends State {
onPressed:
(_selectedSymbol == null) ? null : _changeZIndex,
),
+ FlatButton(
+ child: const Text('get current LatLng'),
+ onPressed: (_selectedSymbol == null)
+ ? null
+ : _getLatLng,
+ ),
],
),
],
diff --git a/example/lib/scrolling_map.dart b/example/lib/scrolling_map.dart
index d31cf9dba..e1d693dc1 100644
--- a/example/lib/scrolling_map.dart
+++ b/example/lib/scrolling_map.dart
@@ -8,19 +8,28 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:mapbox_gl/mapbox_gl.dart';
+import 'main.dart';
import 'page.dart';
-class ScrollingMapPage extends Page {
+class ScrollingMapPage extends ExamplePage {
ScrollingMapPage() : super(const Icon(Icons.map), 'Scrolling map');
@override
Widget build(BuildContext context) {
- return const ScrollingMapBody();
+ return ScrollingMapBody();
}
}
-class ScrollingMapBody extends StatelessWidget {
- const ScrollingMapBody();
+class ScrollingMapBody extends StatefulWidget {
+ ScrollingMapBody();
+
+ @override
+ _ScrollingMapBodyState createState() => _ScrollingMapBodyState();
+}
+
+class _ScrollingMapBodyState extends State {
+ MapboxMapController controllerOne;
+ MapboxMapController controllerTwo;
final LatLng center = const LatLng(32.080664, 34.9563837);
@@ -42,7 +51,9 @@ class ScrollingMapBody extends StatelessWidget {
width: 300.0,
height: 300.0,
child: MapboxMap(
- onMapCreated: onMapCreated,
+ accessToken: MapsDemo.ACCESS_TOKEN,
+ onMapCreated: onMapCreatedOne,
+ onStyleLoadedCallback: () => onStyleLoaded(controllerOne),
initialCameraPosition: CameraPosition(
target: center,
zoom: 11.0,
@@ -76,7 +87,9 @@ class ScrollingMapBody extends StatelessWidget {
width: 300.0,
height: 300.0,
child: MapboxMap(
- onMapCreated: onMapCreated,
+ accessToken: MapsDemo.ACCESS_TOKEN,
+ onMapCreated: onMapCreatedTwo,
+ onStyleLoadedCallback: () => onStyleLoaded(controllerTwo),
initialCameraPosition: CameraPosition(
target: center,
zoom: 11.0,
@@ -98,7 +111,15 @@ class ScrollingMapBody extends StatelessWidget {
);
}
- void onMapCreated(MapboxMapController controller) {
+ void onMapCreatedOne(MapboxMapController controller) {
+ this.controllerOne = controller;
+ }
+
+ void onMapCreatedTwo(MapboxMapController controller) {
+ this.controllerTwo = controller;
+ }
+
+ void onStyleLoaded(MapboxMapController controller) {
controller.addSymbol(SymbolOptions(
geometry: LatLng(
center.latitude,
diff --git a/example/macos/.gitignore b/example/macos/.gitignore
new file mode 100644
index 000000000..d2fd37723
--- /dev/null
+++ b/example/macos/.gitignore
@@ -0,0 +1,6 @@
+# Flutter-related
+**/Flutter/ephemeral/
+**/Pods/
+
+# Xcode-related
+**/xcuserdata/
diff --git a/example/macos/Podfile b/example/macos/Podfile
new file mode 100644
index 000000000..d60ec7102
--- /dev/null
+++ b/example/macos/Podfile
@@ -0,0 +1,82 @@
+platform :osx, '10.11'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def parse_KV_file(file, separator='=')
+ file_abs_path = File.expand_path(file)
+ if !File.exists? file_abs_path
+ return [];
+ end
+ pods_ary = []
+ skip_line_start_symbols = ["#", "/"]
+ File.foreach(file_abs_path) { |line|
+ next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
+ plugin = line.split(pattern=separator)
+ if plugin.length == 2
+ podname = plugin[0].strip()
+ path = plugin[1].strip()
+ podpath = File.expand_path("#{path}", file_abs_path)
+ pods_ary.push({:name => podname, :path => podpath});
+ else
+ puts "Invalid plugin specification: #{line}"
+ end
+ }
+ return pods_ary
+end
+
+def pubspec_supports_macos(file)
+ file_abs_path = File.expand_path(file)
+ if !File.exists? file_abs_path
+ return false;
+ end
+ File.foreach(file_abs_path) { |line|
+ return true if line =~ /^\s*macos:/
+ }
+ return false
+end
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
+ # referring to absolute paths on developers' machines.
+ ephemeral_dir = File.join('Flutter', 'ephemeral')
+ symlink_dir = File.join(ephemeral_dir, '.symlinks')
+ symlink_plugins_dir = File.join(symlink_dir, 'plugins')
+ system("rm -rf #{symlink_dir}")
+ system("mkdir -p #{symlink_plugins_dir}")
+
+ # Flutter Pods
+ generated_xcconfig = parse_KV_file(File.join(ephemeral_dir, 'Flutter-Generated.xcconfig'))
+ if generated_xcconfig.empty?
+ puts "Flutter-Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
+ end
+ generated_xcconfig.map { |p|
+ if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
+ symlink = File.join(symlink_dir, 'flutter')
+ File.symlink(File.dirname(p[:path]), symlink)
+ pod 'FlutterMacOS', :path => File.join(symlink, File.basename(p[:path]))
+ end
+ }
+
+ # Plugin Pods
+ plugin_pods = parse_KV_file('../.flutter-plugins')
+ plugin_pods.map { |p|
+ symlink = File.join(symlink_plugins_dir, p[:name])
+ File.symlink(p[:path], symlink)
+ if pubspec_supports_macos(File.join(symlink, 'pubspec.yaml'))
+ pod p[:name], :path => File.join(symlink, 'macos')
+ end
+ }
+end
+
+# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
+install! 'cocoapods', :disable_input_output_paths => true
diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 000000000..331479d39
--- /dev/null
+++ b/example/macos/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,596 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
+ buildPhases = (
+ 33CC111E2044C6BF0003C045 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = "Flutter Assemble";
+ productName = FLX;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+ 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; };
+ 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ D73912F022F37F9E000D13A0 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; };
+ D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 33CC111A2044C6BA0003C045;
+ remoteInfo = FLX;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 33CC110E2044A8840003C045 /* Bundle Framework */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */,
+ 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */,
+ );
+ name = "Bundle Framework";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
+ 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
+ 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
+ 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; };
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; };
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; };
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; };
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; };
+ 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FlutterMacOS.framework; path = Flutter/ephemeral/FlutterMacOS.framework; sourceTree = SOURCE_ROOT; };
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
+ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
+ D73912EF22F37F9E000D13A0 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/ephemeral/App.framework; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 33CC10EA2044A3C60003C045 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D73912F022F37F9E000D13A0 /* App.framework in Frameworks */,
+ 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 33BA886A226E78AF003329D5 /* Configs */ = {
+ isa = PBXGroup;
+ children = (
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
+ );
+ path = Configs;
+ sourceTree = "";
+ };
+ 33CC10E42044A3C60003C045 = {
+ isa = PBXGroup;
+ children = (
+ 33FAB671232836740065AC1E /* Runner */,
+ 33CEB47122A05771004F2AC0 /* Flutter */,
+ 33CC10EE2044A3C60003C045 /* Products */,
+ D73912EC22F37F3D000D13A0 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ 33CC10EE2044A3C60003C045 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10ED2044A3C60003C045 /* example.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 33CC11242044D66E0003C045 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */,
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */,
+ 33CC10F72044A3C60003C045 /* Info.plist */,
+ );
+ name = Resources;
+ path = ..;
+ sourceTree = "";
+ };
+ 33CEB47122A05771004F2AC0 /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
+ D73912EF22F37F9E000D13A0 /* App.framework */,
+ 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */,
+ );
+ path = Flutter;
+ sourceTree = "";
+ };
+ 33FAB671232836740065AC1E /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
+ 33E51914231749380026EE4D /* Release.entitlements */,
+ 33CC11242044D66E0003C045 /* Resources */,
+ 33BA886A226E78AF003329D5 /* Configs */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ D73912EC22F37F3D000D13A0 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 33CC10EC2044A3C60003C045 /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 33CC10E92044A3C60003C045 /* Sources */,
+ 33CC10EA2044A3C60003C045 /* Frameworks */,
+ 33CC10EB2044A3C60003C045 /* Resources */,
+ 33CC110E2044A8840003C045 /* Bundle Framework */,
+ 3399D490228B24CF009A79C7 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */,
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 33CC10ED2044A3C60003C045 /* example.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 33CC10E52044A3C60003C045 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 0930;
+ ORGANIZATIONNAME = "The Flutter Authors";
+ TargetAttributes = {
+ 33CC10EC2044A3C60003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 1100;
+ ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 1;
+ };
+ };
+ };
+ 33CC111A2044C6BA0003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Manual;
+ };
+ };
+ };
+ buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 33CC10E42044A3C60003C045;
+ productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 33CC10EC2044A3C60003C045 /* Runner */,
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 33CC10EB2044A3C60003C045 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3399D490228B24CF009A79C7 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n";
+ };
+ 33CC111E2044C6BF0003C045 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ Flutter/ephemeral/FlutterInputs.xcfilelist,
+ );
+ inputPaths = (
+ Flutter/ephemeral/tripwire,
+ );
+ outputFileListPaths = (
+ Flutter/ephemeral/FlutterOutputs.xcfilelist,
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh\ntouch Flutter/ephemeral/tripwire\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 33CC10E92044A3C60003C045 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
+ targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 33CC10F52044A3C60003C045 /* Base */,
+ );
+ name = MainMenu.xib;
+ path = Runner;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 338D0CE9231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Profile;
+ };
+ 338D0CEA231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter/ephemeral",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Profile;
+ };
+ 338D0CEB231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Profile;
+ };
+ 33CC10F92044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 33CC10FA2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ 33CC10FC2044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter/ephemeral",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 33CC10FD2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter/ephemeral",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ 33CC111C2044C6BA0003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 33CC111D2044C6BA0003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10F92044A3C60003C045 /* Debug */,
+ 33CC10FA2044A3C60003C045 /* Release */,
+ 338D0CE9231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10FC2044A3C60003C045 /* Debug */,
+ 33CC10FD2044A3C60003C045 /* Release */,
+ 338D0CEA231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC111C2044C6BA0003C045 /* Debug */,
+ 33CC111D2044C6BA0003C045 /* Release */,
+ 338D0CEB231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 33CC10E52044A3C60003C045 /* Project object */;
+}
diff --git a/example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000..764c74b8d
--- /dev/null
+++ b/example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000..18d981003
--- /dev/null
+++ b/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 000000000..df12c333e
--- /dev/null
+++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/example/macos/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 000000000..1d526a16e
--- /dev/null
+++ b/example/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 000000000..18d981003
--- /dev/null
+++ b/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/example/macos/Runner/AppDelegate.swift b/example/macos/Runner/AppDelegate.swift
new file mode 100644
index 000000000..d53ef6437
--- /dev/null
+++ b/example/macos/Runner/AppDelegate.swift
@@ -0,0 +1,9 @@
+import Cocoa
+import FlutterMacOS
+
+@NSApplicationMain
+class AppDelegate: FlutterAppDelegate {
+ override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
+ return true
+ }
+}
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 000000000..a2ec33f19
--- /dev/null
+++ b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+ "images" : [
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_16.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_64.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_128.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_1024.png",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
new file mode 100644
index 000000000..3c4935a7c
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
new file mode 100644
index 000000000..ed4cc1642
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
new file mode 100644
index 000000000..483be6138
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
new file mode 100644
index 000000000..bcbf36df2
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
new file mode 100644
index 000000000..9c0a65286
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
new file mode 100644
index 000000000..e71a72613
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ
diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
new file mode 100644
index 000000000..8a31fe2dd
Binary files /dev/null and b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ
diff --git a/example/macos/Runner/Base.lproj/MainMenu.xib b/example/macos/Runner/Base.lproj/MainMenu.xib
new file mode 100644
index 000000000..537341abf
--- /dev/null
+++ b/example/macos/Runner/Base.lproj/MainMenu.xib
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/macos/Runner/Configs/AppInfo.xcconfig b/example/macos/Runner/Configs/AppInfo.xcconfig
new file mode 100644
index 000000000..4fa23d759
--- /dev/null
+++ b/example/macos/Runner/Configs/AppInfo.xcconfig
@@ -0,0 +1,14 @@
+// Application-level settings for the Runner target.
+//
+// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
+// future. If not, the values below would default to using the project name when this becomes a
+// 'flutter create' template.
+
+// The application's name. By default this is also the title of the Flutter window.
+PRODUCT_NAME = example
+
+// The application's bundle identifier
+PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.example
+
+// The copyright displayed in application information
+PRODUCT_COPYRIGHT = Copyright © 2020 com.mapbox. All rights reserved.
diff --git a/example/macos/Runner/Configs/Debug.xcconfig b/example/macos/Runner/Configs/Debug.xcconfig
new file mode 100644
index 000000000..36b0fd946
--- /dev/null
+++ b/example/macos/Runner/Configs/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Debug.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/example/macos/Runner/Configs/Release.xcconfig b/example/macos/Runner/Configs/Release.xcconfig
new file mode 100644
index 000000000..dff4f4956
--- /dev/null
+++ b/example/macos/Runner/Configs/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Release.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/example/macos/Runner/Configs/Warnings.xcconfig b/example/macos/Runner/Configs/Warnings.xcconfig
new file mode 100644
index 000000000..42bcbf478
--- /dev/null
+++ b/example/macos/Runner/Configs/Warnings.xcconfig
@@ -0,0 +1,13 @@
+WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
+GCC_WARN_UNDECLARED_SELECTOR = YES
+CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
+CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_PRAGMA_PACK = YES
+CLANG_WARN_STRICT_PROTOTYPES = YES
+CLANG_WARN_COMMA = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
+GCC_WARN_SHADOW = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
diff --git a/example/macos/Runner/DebugProfile.entitlements b/example/macos/Runner/DebugProfile.entitlements
new file mode 100644
index 000000000..dddb8a30c
--- /dev/null
+++ b/example/macos/Runner/DebugProfile.entitlements
@@ -0,0 +1,12 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.network.server
+
+
+
diff --git a/example/macos/Runner/Info.plist b/example/macos/Runner/Info.plist
new file mode 100644
index 000000000..4789daa6a
--- /dev/null
+++ b/example/macos/Runner/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ $(PRODUCT_COPYRIGHT)
+ NSMainNibFile
+ MainMenu
+ NSPrincipalClass
+ NSApplication
+
+
diff --git a/example/macos/Runner/MainFlutterWindow.swift b/example/macos/Runner/MainFlutterWindow.swift
new file mode 100644
index 000000000..2722837ec
--- /dev/null
+++ b/example/macos/Runner/MainFlutterWindow.swift
@@ -0,0 +1,15 @@
+import Cocoa
+import FlutterMacOS
+
+class MainFlutterWindow: NSWindow {
+ override func awakeFromNib() {
+ let flutterViewController = FlutterViewController.init()
+ let windowFrame = self.frame
+ self.contentViewController = flutterViewController
+ self.setFrame(windowFrame, display: true)
+
+ RegisterGeneratedPlugins(registry: flutterViewController)
+
+ super.awakeFromNib()
+ }
+}
diff --git a/example/macos/Runner/Release.entitlements b/example/macos/Runner/Release.entitlements
new file mode 100644
index 000000000..852fa1a47
--- /dev/null
+++ b/example/macos/Runner/Release.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+
+
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 95c648eb6..e79256f80 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -12,7 +12,14 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
- location: ^2.3.5
+ location: ^2.5.3
+ http:
+
+dependency_overrides:
+ mapbox_gl_platform_interface:
+ path: ../mapbox_gl_platform_interface
+ mapbox_gl_web:
+ path: ../mapbox_gl_web
dev_dependencies:
flutter_test:
@@ -44,6 +51,7 @@ flutter:
- assets/symbols/custom-icon.png
- assets/symbols/2.0x/custom-icon.png
- assets/symbols/3.0x/custom-icon.png
+ - assets/style.json
# For details regarding adding assets from package dependencies, see
# https://flutter.io/assets-and-images/#from-packages
diff --git a/example/web/favicon.png b/example/web/favicon.png
new file mode 100644
index 000000000..8aaa46ac1
Binary files /dev/null and b/example/web/favicon.png differ
diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png
new file mode 100644
index 000000000..b749bfef0
Binary files /dev/null and b/example/web/icons/Icon-192.png differ
diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png
new file mode 100644
index 000000000..88cfd48df
Binary files /dev/null and b/example/web/icons/Icon-512.png differ
diff --git a/example/web/index.html b/example/web/index.html
new file mode 100644
index 000000000..0ece3caab
--- /dev/null
+++ b/example/web/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ example
+
+
+
+
+
+
+
+
diff --git a/example/web/manifest.json b/example/web/manifest.json
new file mode 100644
index 000000000..c63800102
--- /dev/null
+++ b/example/web/manifest.json
@@ -0,0 +1,23 @@
+{
+ "name": "example",
+ "short_name": "example",
+ "start_url": ".",
+ "display": "minimal-ui",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "A new Flutter project.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ]
+}
diff --git a/ios/Classes/Convert.swift b/ios/Classes/Convert.swift
index 84b6c4de8..e7dfd85bb 100644
--- a/ios/Classes/Convert.swift
+++ b/ios/Classes/Convert.swift
@@ -37,6 +37,9 @@ class Convert {
if let myLocationTrackingMode = options["myLocationTrackingMode"] as? UInt, let trackingMode = MGLUserTrackingMode(rawValue: myLocationTrackingMode) {
delegate.setMyLocationTrackingMode(myLocationTrackingMode: trackingMode)
}
+ if let myLocationRenderMode = options["myLocationRenderMode"] as? Int, let renderMode = MyLocationRenderMode(rawValue: myLocationRenderMode) {
+ delegate.setMyLocationRenderMode(myLocationRenderMode: renderMode)
+ }
if let logoViewMargins = options["logoViewMargins"] as? [Double] {
delegate.setLogoViewMargins(x: logoViewMargins[0], y: logoViewMargins[1])
}
diff --git a/ios/Classes/Enums.swift b/ios/Classes/Enums.swift
new file mode 100644
index 000000000..6d621d344
--- /dev/null
+++ b/ios/Classes/Enums.swift
@@ -0,0 +1,3 @@
+enum MyLocationRenderMode: Int {
+ case Normal, Compass, Gps
+}
diff --git a/ios/Classes/MapboxMapController.swift b/ios/Classes/MapboxMapController.swift
index f663cb5fc..6384ee51a 100644
--- a/ios/Classes/MapboxMapController.swift
+++ b/ios/Classes/MapboxMapController.swift
@@ -26,6 +26,11 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
}
init(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?, registrar: FlutterPluginRegistrar) {
+ if let args = args as? [String: Any] {
+ if let token = args["accessToken"] as? NSString{
+ MGLAccountManager.accessToken = token
+ }
+ }
mapView = MGLMapView(frame: frame)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.registrar = registrar
@@ -43,6 +48,12 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
}
mapView.addGestureRecognizer(singleTap)
+ let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleMapLongPress(sender:)))
+ for recognizer in mapView.gestureRecognizers! where recognizer is UILongPressGestureRecognizer {
+ longPress.require(toFail: recognizer)
+ }
+ mapView.addGestureRecognizer(longPress)
+
if let args = args as? [String: Any] {
Convert.interpretMapboxMapOptions(options: args["options"], delegate: self)
if let initialCameraPosition = args["initialCameraPosition"] as? [String: Any],
@@ -112,6 +123,34 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
style.localizeLabels(into: locale)
}
result(nil)
+ case "map#queryRenderedFeatures":
+ guard let arguments = methodCall.arguments as? [String: Any] else { return }
+ let layerIds = arguments["layerIds"] as? Set
+ var filterExpression: NSPredicate?
+ if let filter = arguments["filter"] as? [Any] {
+ filterExpression = NSPredicate(mglJSONObject: filter)
+ }
+ var reply = [String: NSObject]()
+ var features:[MGLFeature] = []
+ if let x = arguments["x"] as? Double, let y = arguments["y"] as? Double {
+ features = mapView.visibleFeatures(at: CGPoint(x: x, y: y), styleLayerIdentifiers: layerIds, predicate: filterExpression)
+ }
+ if let top = arguments["top"] as? Double,
+ let bottom = arguments["bottom"] as? Double,
+ let left = arguments["left"] as? Double,
+ let right = arguments["right"] as? Double {
+ features = mapView.visibleFeatures(in: CGRect(x: left, y: top, width: right, height: bottom), styleLayerIdentifiers: layerIds, predicate: filterExpression)
+ }
+ var featuresJson = [String]()
+ for feature in features {
+ let dictionary = feature.geoJSONDictionary()
+ if let theJSONData = try? JSONSerialization.data(withJSONObject: dictionary, options: []),
+ let theJSONText = String(data: theJSONData, encoding: .ascii) {
+ featuresJson.append(theJSONText)
+ }
+ }
+ reply["features"] = featuresJson as NSObject
+ result(reply)
case "map#setTelemetryEnabled":
guard let arguments = methodCall.arguments as? [String: Any] else { return }
let telemetryEnabled = arguments["enabled"] as? Bool
@@ -137,26 +176,30 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
guard let arguments = methodCall.arguments as? [String: Any] else { return }
guard let cameraUpdate = arguments["cameraUpdate"] as? [Any] else { return }
if let camera = Convert.parseCameraUpdate(cameraUpdate: cameraUpdate, mapView: mapView) {
+ if let duration = arguments["duration"] as? TimeInterval {
+ mapView.setCamera(camera, withDuration: TimeInterval(duration / 1000),
+ animationTimingFunction: CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut))
+ result(nil)
+ }
mapView.setCamera(camera, animated: true)
}
result(nil)
- case "symbol#add":
+ case "symbols#addAll":
guard let symbolAnnotationController = symbolAnnotationController else { return }
guard let arguments = methodCall.arguments as? [String: Any] else { return }
-
- // Parse geometry
- if let options = arguments["options"] as? [String: Any],
- let geometry = options["geometry"] as? [Double] {
- // Convert geometry to coordinate and create symbol.
- let coordinate = CLLocationCoordinate2DMake(geometry[0], geometry[1])
- let symbol = MGLSymbolStyleAnnotation(coordinate: coordinate)
- Convert.interpretSymbolOptions(options: arguments["options"], delegate: symbol)
- // Load icon image from asset if an icon name is supplied.
- if let iconImage = options["iconImage"] as? String {
- addIconImageToMap(iconImageName: iconImage)
+
+ if let options = arguments["options"] as? [[String: Any]] {
+ var symbols: [MGLSymbolStyleAnnotation] = [];
+ for o in options {
+ if let symbol = getSymbolForOptions(options: o) {
+ symbols.append(symbol)
+ }
}
- symbolAnnotationController.addStyleAnnotation(symbol)
- result(symbol.identifier)
+ if !symbols.isEmpty {
+ symbolAnnotationController.addStyleAnnotations(symbols)
+ }
+
+ result(symbols.map { $0.identifier })
} else {
result(nil)
}
@@ -178,18 +221,58 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
}
}
result(nil)
- case "symbol#remove":
+ case "symbols#removeAll":
+ guard let symbolAnnotationController = symbolAnnotationController else { return }
+ guard let arguments = methodCall.arguments as? [String: Any] else { return }
+ guard let symbolIds = arguments["symbols"] as? [String] else { return }
+ var symbols: [MGLSymbolStyleAnnotation] = [];
+
+ for symbol in symbolAnnotationController.styleAnnotations(){
+ if symbolIds.contains(symbol.identifier) {
+ symbols.append(symbol as! MGLSymbolStyleAnnotation)
+ }
+ }
+ symbolAnnotationController.removeStyleAnnotations(symbols)
+ result(nil)
+ case "symbol#getGeometry":
guard let symbolAnnotationController = symbolAnnotationController else { return }
guard let arguments = methodCall.arguments as? [String: Any] else { return }
guard let symbolId = arguments["symbol"] as? String else { return }
+ var reply: [String:Double]? = nil
for symbol in symbolAnnotationController.styleAnnotations(){
if symbol.identifier == symbolId {
- symbolAnnotationController.removeStyleAnnotation(symbol)
+ if let geometry = symbol.geoJSONDictionary["geometry"] as? [String: Any],
+ let coordinates = geometry["coordinates"] as? [Double] {
+ reply = ["latitude": coordinates[1], "longitude": coordinates[0]]
+ }
break;
}
}
+ result(reply)
+ case "symbolManager#iconAllowOverlap":
+ guard let symbolAnnotationController = symbolAnnotationController else { return }
+ guard let arguments = methodCall.arguments as? [String: Any] else { return }
+ guard let iconAllowOverlap = arguments["iconAllowOverlap"] as? Bool else { return }
+
+ symbolAnnotationController.iconAllowsOverlap = iconAllowOverlap
result(nil)
+ case "symbolManager#iconIgnorePlacement":
+ guard let symbolAnnotationController = symbolAnnotationController else { return }
+ guard let arguments = methodCall.arguments as? [String: Any] else { return }
+ guard let iconIgnorePlacement = arguments["iconIgnorePlacement"] as? Bool else { return }
+
+ symbolAnnotationController.iconIgnoresPlacement = iconIgnorePlacement
+ result(nil)
+ case "symbolManager#textAllowOverlap":
+ guard let symbolAnnotationController = symbolAnnotationController else { return }
+ guard let arguments = methodCall.arguments as? [String: Any] else { return }
+ guard let textAllowOverlap = arguments["textAllowOverlap"] as? Bool else { return }
+
+ symbolAnnotationController.textAllowsOverlap = textAllowOverlap
+ result(nil)
+ case "symbolManager#textIgnorePlacement":
+ result(FlutterMethodNotImplemented)
case "circle#add":
guard let circleAnnotationController = circleAnnotationController else { return }
guard let arguments = methodCall.arguments as? [String: Any] else { return }
@@ -273,11 +356,57 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
}
}
result(nil)
+ case "line#getGeometry":
+ guard let lineAnnotationController = lineAnnotationController else { return }
+ guard let arguments = methodCall.arguments as? [String: Any] else { return }
+ guard let lineId = arguments["line"] as? String else { return }
+
+ var reply: [Any]? = nil
+ for line in lineAnnotationController.styleAnnotations() {
+ if line.identifier == lineId {
+ if let geometry = line.geoJSONDictionary["geometry"] as? [String: Any],
+ let coordinates = geometry["coordinates"] as? [[Double]] {
+ reply = coordinates.map { [ "latitude": $0[1], "longitude": $0[0] ] }
+ }
+ break;
+ }
+ }
+ result(reply)
+ case "style#addImage":
+ guard let arguments = methodCall.arguments as? [String: Any] else { return }
+ guard let name = arguments["name"] as? String else { return }
+ //guard let length = arguments["length"] as? NSNumber else { return }
+ guard let bytes = arguments["bytes"] as? FlutterStandardTypedData else { return }
+ guard let sdf = arguments["sdf"] as? Bool else { return }
+ guard let data = bytes.data as? Data else{ return }
+ guard let image = UIImage(data: data) else { return }
+ if (sdf) {
+ self.mapView.style?.setImage(image.withRenderingMode(.alwaysTemplate), forName: name)
+ } else {
+ self.mapView.style?.setImage(image, forName: name)
+ }
+ result(nil)
default:
result(FlutterMethodNotImplemented)
}
}
+ private func getSymbolForOptions(options: [String: Any]) -> MGLSymbolStyleAnnotation? {
+ // Parse geometry
+ if let geometry = options["geometry"] as? [Double] {
+ // Convert geometry to coordinate and create symbol.
+ let coordinate = CLLocationCoordinate2DMake(geometry[0], geometry[1])
+ let symbol = MGLSymbolStyleAnnotation(coordinate: coordinate)
+ Convert.interpretSymbolOptions(options: options, delegate: symbol)
+ // Load icon image from asset if an icon name is supplied.
+ if let iconImage = options["iconImage"] as? String {
+ addIconImageToMap(iconImageName: iconImage)
+ }
+ return symbol
+ }
+ return nil
+ }
+
private func addIconImageToMap(iconImageName: String) {
// Check if the image has already been added to the map.
if self.mapView.style?.image(forName: iconImageName) == nil {
@@ -320,6 +449,28 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
])
}
+ /*
+ * UILongPressGestureRecognizer
+ * After a long press invoke the map#onMapLongClick callback.
+ */
+ @objc @IBAction func handleMapLongPress(sender: UILongPressGestureRecognizer) {
+ //Fire when the long press starts
+ if (sender.state == .began) {
+ // Get the CGPoint where the user tapped.
+ let point = sender.location(in: mapView)
+ let coordinate = mapView.convert(point, toCoordinateFrom: mapView)
+ channel?.invokeMethod("map#onMapLongClick", arguments: [
+ "x": point.x,
+ "y": point.y,
+ "lng": coordinate.longitude,
+ "lat": coordinate.latitude,
+ ])
+ }
+
+ }
+
+
+
/*
* MGLAnnotationControllerDelegate
*/
@@ -427,7 +578,6 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
if let symbol = annotation as? Symbol {
channel?.invokeMethod("symbol#onTap", arguments: ["symbol" : "\(symbol.id)"])
-
}
}
@@ -493,6 +643,13 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
} else if (styleString.hasPrefix("{") || styleString.hasPrefix("[")) {
// Currently the iOS Mapbox SDK does not have a builder for json.
NSLog("setStyleString - JSON style currently not supported")
+ } else if (
+ !styleString.hasPrefix("http://") &&
+ !styleString.hasPrefix("https://") &&
+ !styleString.hasPrefix("mapbox://")) {
+ // We are assuming that the style will be loaded from an asset here.
+ let assetPath = registrar.lookupKey(forAsset: styleString)
+ mapView.styleURL = URL(string: assetPath, relativeTo: Bundle.main.resourceURL)
} else {
mapView.styleURL = URL(string: styleString)
}
@@ -522,6 +679,16 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma
func setMyLocationTrackingMode(myLocationTrackingMode: MGLUserTrackingMode) {
mapView.userTrackingMode = myLocationTrackingMode
}
+ func setMyLocationRenderMode(myLocationRenderMode: MyLocationRenderMode) {
+ switch myLocationRenderMode {
+ case .Normal:
+ mapView.showsUserHeadingIndicator = false
+ case .Compass:
+ mapView.showsUserHeadingIndicator = true
+ case .Gps:
+ NSLog("RenderMode.GPS currently not supported")
+ }
+ }
func setLogoViewMargins(x: Double, y: Double) {
mapView.logoViewMargins = CGPoint(x: x, y: y)
}
diff --git a/ios/Classes/MapboxMapOptionsSink.swift b/ios/Classes/MapboxMapOptionsSink.swift
index 6ce226314..2cd2cf746 100644
--- a/ios/Classes/MapboxMapOptionsSink.swift
+++ b/ios/Classes/MapboxMapOptionsSink.swift
@@ -13,6 +13,7 @@ protocol MapboxMapOptionsSink {
func setZoomGesturesEnabled(zoomGesturesEnabled: Bool)
func setMyLocationEnabled(myLocationEnabled: Bool)
func setMyLocationTrackingMode(myLocationTrackingMode: MGLUserTrackingMode)
+ func setMyLocationRenderMode(myLocationRenderMode: MyLocationRenderMode)
func setLogoViewMargins(x: Double, y: Double)
func setCompassViewPosition(position: MGLOrnamentPosition)
func setCompassViewMargins(x: Double, y: Double)
diff --git a/lib/mapbox_gl.dart b/lib/mapbox_gl.dart
index 83c0b15e5..b856b363d 100644
--- a/lib/mapbox_gl.dart
+++ b/lib/mapbox_gl.dart
@@ -6,21 +6,34 @@ library mapbox_gl;
import 'dart:async';
import 'dart:math';
-import 'dart:ui';
+import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'package:mapbox_gl_platform_interface/mapbox_gl_platform_interface.dart';
+
+export 'package:mapbox_gl_platform_interface/mapbox_gl_platform_interface.dart'
+ show
+ LatLng,
+ LatLngBounds,
+ CameraPosition,
+ CameraUpdate,
+ ArgumentCallbacks,
+ Symbol,
+ SymbolOptions,
+ CameraTargetBounds,
+ MinMaxZoomPreference,
+ MapboxStyles,
+ MyLocationTrackingMode,
+ MyLocationRenderMode,
+ Circle,
+ CircleOptions,
+ Line,
+ LineOptions;
part 'src/bitmap.dart';
-part 'src/callbacks.dart';
-part 'src/camera.dart';
part 'src/controller.dart';
part 'src/mapbox_map.dart';
-part 'src/location.dart';
-part 'src/symbol.dart';
-part 'src/line.dart';
-part 'src/circle.dart';
-part 'src/ui.dart';
-part 'src/global.dart';
\ No newline at end of file
+part 'src/global.dart';
diff --git a/lib/src/controller.dart b/lib/src/controller.dart
index ccca05c46..83ed1f2a5 100644
--- a/lib/src/controller.dart
+++ b/lib/src/controller.dart
@@ -5,12 +5,15 @@
part of mapbox_gl;
typedef void OnMapClickCallback(Point point, LatLng coordinates);
+typedef void OnMapLongClickCallback(Point point, LatLng coordinates);
typedef void OnStyleLoadedCallback();
typedef void OnCameraTrackingDismissedCallback();
typedef void OnCameraTrackingChangedCallback(MyLocationTrackingMode mode);
+typedef void OnCameraIdleCallback();
+
typedef void OnMapIdleCallback();
/// Controller for a single MapboxMap instance running on the host platform.
@@ -29,48 +32,139 @@ typedef void OnMapIdleCallback();
/// Line tap events can be received by adding callbacks to [onLineTapped].
/// Circle tap events can be received by adding callbacks to [onCircleTapped].
class MapboxMapController extends ChangeNotifier {
- MapboxMapController._(
- this._id, MethodChannel channel, CameraPosition initialCameraPosition,
+ MapboxMapController._(this._id, CameraPosition initialCameraPosition,
{this.onStyleLoadedCallback,
this.onMapClick,
+ this.onMapLongClick,
this.onCameraTrackingDismissed,
this.onCameraTrackingChanged,
+ this.onCameraIdle,
this.onMapIdle})
- : assert(_id != null),
- assert(channel != null),
- _channel = channel {
+ : assert(_id != null) {
_cameraPosition = initialCameraPosition;
- _channel.setMethodCallHandler(_handleMethodCall);
+
+ MapboxGlPlatform.getInstance(_id)
+ .onInfoWindowTappedPlatform
+ .add((symbolId) {
+ final Symbol symbol = _symbols[symbolId];
+ if (symbol != null) {
+ onInfoWindowTapped(symbol);
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id).onSymbolTappedPlatform.add((symbolId) {
+ final Symbol symbol = _symbols[symbolId];
+ if (symbol != null) {
+ onSymbolTapped(symbol);
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id).onLineTappedPlatform.add((lineId) {
+ final Line line = _lines[lineId];
+ if (line != null) {
+ onLineTapped(line);
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id).onCircleTappedPlatform.add((circleId) {
+ final Circle circle = _circles[circleId];
+ if (circle != null) {
+ onCircleTapped(circle);
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id).onCameraMoveStartedPlatform.add((_) {
+ _isCameraMoving = true;
+ notifyListeners();
+ });
+
+ MapboxGlPlatform.getInstance(_id)
+ .onCameraMovePlatform
+ .add((cameraPosition) {
+ _cameraPosition = cameraPosition;
+ notifyListeners();
+ });
+
+ MapboxGlPlatform.getInstance(_id).onCameraIdlePlatform.add((_) {
+ _isCameraMoving = false;
+ if (onCameraIdle != null) {
+ onCameraIdle();
+ }
+ notifyListeners();
+ });
+
+ MapboxGlPlatform.getInstance(_id).onMapStyleLoadedPlatform.add((_) {
+ if (onStyleLoadedCallback != null) {
+ onStyleLoadedCallback();
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id).onMapClickPlatform.add((dict) {
+ if (onMapClick != null) {
+ onMapClick(dict['point'], dict['latLng']);
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id).onMapLongClickPlatform.add((dict) {
+ if (onMapLongClick != null) {
+ onMapLongClick(dict['point'], dict['latLng']);
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id)
+ .onCameraTrackingChangedPlatform
+ .add((mode) {
+ if (onCameraTrackingChanged != null) {
+ onCameraTrackingChanged(mode);
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id)
+ .onCameraTrackingDismissedPlatform
+ .add((_) {
+ if (onCameraTrackingDismissed != null) {
+ onCameraTrackingDismissed();
+ }
+ });
+
+ MapboxGlPlatform.getInstance(_id).onMapIdlePlatform.add((_) {
+ if (onMapIdle != null) {
+ onMapIdle();
+ }
+ });
}
static Future init(
int id, CameraPosition initialCameraPosition,
{OnStyleLoadedCallback onStyleLoadedCallback,
OnMapClickCallback onMapClick,
+ OnMapLongClickCallback onMapLongClick,
OnCameraTrackingDismissedCallback onCameraTrackingDismissed,
OnCameraTrackingChangedCallback onCameraTrackingChanged,
+ OnCameraIdleCallback onCameraIdle,
OnMapIdleCallback onMapIdle}) async {
assert(id != null);
- final MethodChannel channel =
- MethodChannel('plugins.flutter.io/mapbox_maps_$id');
- await channel.invokeMethod('map#waitForMap');
- return MapboxMapController._(id, channel, initialCameraPosition,
+ await MapboxGlPlatform.getInstance(id).initPlatform(id);
+ return MapboxMapController._(id, initialCameraPosition,
onStyleLoadedCallback: onStyleLoadedCallback,
onMapClick: onMapClick,
+ onMapLongClick: onMapLongClick,
onCameraTrackingDismissed: onCameraTrackingDismissed,
onCameraTrackingChanged: onCameraTrackingChanged,
+ onCameraIdle: onCameraIdle,
onMapIdle: onMapIdle);
}
- final MethodChannel _channel;
-
final OnStyleLoadedCallback onStyleLoadedCallback;
final OnMapClickCallback onMapClick;
+ final OnMapLongClickCallback onMapLongClick;
final OnCameraTrackingDismissedCallback onCameraTrackingDismissed;
final OnCameraTrackingChangedCallback onCameraTrackingChanged;
+ final OnCameraIdleCallback onCameraIdle;
+
final OnMapIdleCallback onMapIdle;
/// Callbacks to receive tap events for symbols placed on this map.
@@ -115,81 +209,12 @@ class MapboxMapController extends ChangeNotifier {
final int _id; //ignore: unused_field
- Future _handleMethodCall(MethodCall call) async {
- switch (call.method) {
- case 'infoWindow#onTap':
- final String symbolId = call.arguments['symbol'];
- final Symbol symbol = _symbols[symbolId];
- if (symbol != null) {
- onInfoWindowTapped(symbol);
- }
- break;
- case 'symbol#onTap':
- final String symbolId = call.arguments['symbol'];
- final Symbol symbol = _symbols[symbolId];
- if (symbol != null) {
- onSymbolTapped(symbol);
- }
- break;
- case 'line#onTap':
- final String lineId = call.arguments['line'];
- final Line line = _lines[lineId];
- if (line != null) {
- onLineTapped(line);
- }
- break;
- case 'circle#onTap':
- final String circleId = call.arguments['circle'];
- final Circle circle = _circles[circleId];
- if (circle != null) {
- onCircleTapped(circle);
- }
- break;
- case 'camera#onMoveStarted':
- _isCameraMoving = true;
- notifyListeners();
- break;
- case 'camera#onMove':
- _cameraPosition = CameraPosition.fromMap(call.arguments['position']);
- notifyListeners();
- break;
- case 'camera#onIdle':
- _isCameraMoving = false;
- notifyListeners();
- break;
- case 'map#onStyleLoaded':
- if (onStyleLoadedCallback != null) {
- onStyleLoadedCallback();
- }
- break;
- case 'map#onMapClick':
- final double x = call.arguments['x'];
- final double y = call.arguments['y'];
- final double lng = call.arguments['lng'];
- final double lat = call.arguments['lat'];
- if (onMapClick != null) {
- onMapClick(Point(x, y), LatLng(lat, lng));
- }
- break;
- case 'map#onCameraTrackingChanged':
- if (onCameraTrackingChanged != null) {
- final int mode = call.arguments['mode'];
- onCameraTrackingChanged(MyLocationTrackingMode.values[mode]);
- }
- break;
- case 'map#onCameraTrackingDismissed':
- if (onCameraTrackingDismissed != null) {
- onCameraTrackingDismissed();
- }
- break;
- case 'map#onIdle':
- if (onMapIdle != null) {
- onMapIdle();
- }
- break;
- default:
- throw MissingPluginException();
- }
+ Widget buildView(
+ Map creationParams,
+ Function onPlatformViewCreated,
+ Set> gestureRecognizers) {
+ return MapboxGlPlatform.getInstance(_id)
+ .buildView(creationParams, onPlatformViewCreated, gestureRecognizers);
}
/// Updates configuration options of the map user interface.
@@ -200,13 +225,8 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes after listeners have been notified.
Future _updateMapOptions(Map optionsUpdate) async {
assert(optionsUpdate != null);
- final dynamic json = await _channel.invokeMethod(
- 'map#update',
- {
- 'options': optionsUpdate,
- },
- );
- _cameraPosition = CameraPosition.fromMap(json);
+ _cameraPosition =
+ await MapboxGlPlatform.getInstance(_id).updateMapOptions(optionsUpdate);
notifyListeners();
}
@@ -217,9 +237,8 @@ class MapboxMapController extends ChangeNotifier {
/// It returns true if the camera was successfully moved and false if the movement was canceled.
/// Note: this currently always returns immediately with a value of null on iOS
Future animateCamera(CameraUpdate cameraUpdate) async {
- return await _channel.invokeMethod('camera#animate', {
- 'cameraUpdate': cameraUpdate._toJson(),
- });
+ assert(cameraUpdate != null);
+ return MapboxGlPlatform.getInstance(_id).animateCamera(cameraUpdate);
}
/// Instantaneously re-position the camera.
@@ -230,9 +249,7 @@ class MapboxMapController extends ChangeNotifier {
/// It returns true if the camera was successfully moved and false if the movement was canceled.
/// Note: this currently always returns immediately with a value of null on iOS
Future moveCamera(CameraUpdate cameraUpdate) async {
- return await _channel.invokeMethod('camera#move', {
- 'cameraUpdate': cameraUpdate._toJson(),
- });
+ return MapboxGlPlatform.getInstance(_id).moveCamera(cameraUpdate);
}
/// Updates user location tracking mode.
@@ -241,20 +258,19 @@ class MapboxMapController extends ChangeNotifier {
/// platform side.
Future updateMyLocationTrackingMode(
MyLocationTrackingMode myLocationTrackingMode) async {
- await _channel.invokeMethod(
- 'map#updateMyLocationTrackingMode', {
- 'mode': myLocationTrackingMode.index,
- });
+ return MapboxGlPlatform.getInstance(_id)
+ .updateMyLocationTrackingMode(myLocationTrackingMode);
}
-
+
/// Updates the language of the map labels to match the device's language.
///
/// The returned [Future] completes after the change has been made on the
/// platform side.
Future matchMapLanguageWithDeviceDefault() async {
- await _channel.invokeMethod('map#matchMapLanguageWithDeviceDefault');
- }
-
+ return MapboxGlPlatform.getInstance(_id)
+ .matchMapLanguageWithDeviceDefault();
+ }
+
/// Updates the distance from the edges of the map view’s frame to the edges
/// of the map view’s logical viewport, optionally animating the change.
///
@@ -268,15 +284,8 @@ class MapboxMapController extends ChangeNotifier {
/// platform side.
Future updateContentInsets(EdgeInsets insets,
[bool animated = false]) async {
- await _channel.invokeMethod('map#updateContentInsets', {
- 'bounds': {
- 'top': insets.top,
- 'left': insets.left,
- 'bottom': insets.bottom,
- 'right': insets.right,
- },
- 'animated': animated,
- });
+ return MapboxGlPlatform.getInstance(_id)
+ .updateContentInsets(insets, animated);
}
/// Updates the language of the map labels to match the specified language.
@@ -285,19 +294,15 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes after the change has been made on the
/// platform side.
Future setMapLanguage(String language) async {
- await _channel.invokeMethod('map#setMapLanguage', {
- 'language': language,
- });
+ return MapboxGlPlatform.getInstance(_id).setMapLanguage(language);
}
-
+
/// Enables or disables the collection of anonymized telemetry data.
///
/// The returned [Future] completes after the change has been made on the
/// platform side.
Future setTelemetryEnabled(bool enabled) async {
- await _channel.invokeMethod('map#setTelemetryEnabled', {
- 'enabled': enabled,
- });
+ return MapboxGlPlatform.getInstance(_id).setTelemetryEnabled(enabled);
}
/// Retrieves whether collection of anonymized telemetry data is enabled.
@@ -305,7 +310,7 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes after the query has been made on the
/// platform side.
Future getTelemetryEnabled() async {
- return await _channel.invokeMethod('map#getTelemetryEnabled');
+ return MapboxGlPlatform.getInstance(_id).getTelemetryEnabled();
}
/// Adds a symbol to the map, configured using the specified custom [options].
@@ -316,18 +321,21 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes with the added symbol once listeners have
/// been notified.
Future addSymbol(SymbolOptions options, [Map data]) async {
- final SymbolOptions effectiveOptions =
- SymbolOptions.defaultOptions.copyWith(options);
- final String symbolId = await _channel.invokeMethod(
- 'symbol#add',
- {
- 'options': effectiveOptions._toJson(),
- },
- );
- final Symbol symbol = Symbol(symbolId, effectiveOptions, data);
- _symbols[symbolId] = symbol;
+ List result = await addSymbols([options], [data]);
+
+ return result.first;
+ }
+
+
+ Future> addSymbols(List options, [List data]) async {
+ final List effectiveOptions = options.map(
+ (o) => SymbolOptions.defaultOptions.copyWith(o)
+ ).toList();
+
+ final symbols = await MapboxGlPlatform.getInstance(_id).addSymbols(effectiveOptions, data);
+ symbols.forEach((s) => _symbols[s.id] = s);
notifyListeners();
- return symbol;
+ return symbols;
}
/// Updates the specified [symbol] with the given [changes]. The symbol must
@@ -339,14 +347,23 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes once listeners have been notified.
Future updateSymbol(Symbol symbol, SymbolOptions changes) async {
assert(symbol != null);
- assert(_symbols[symbol._id] == symbol);
+ assert(_symbols[symbol.id] == symbol);
assert(changes != null);
- await _channel.invokeMethod('symbol#update', {
- 'symbol': symbol._id,
- 'options': changes._toJson(),
- });
- symbol._options = symbol._options.copyWith(changes);
+ await MapboxGlPlatform.getInstance(_id).updateSymbol(symbol, changes);
+ symbol.options = symbol.options.copyWith(changes);
+ notifyListeners();
+ }
+
+ /// Retrieves the current position of the symbol.
+ /// This may be different from the value of `symbol.options.geometry` if the symbol is draggable.
+ /// In that case this method provides the symbol's actual position, and `symbol.options.geometry` the last programmatically set position.
+ Future getSymbolLatLng(Symbol symbol) async {
+ assert(symbol != null);
+ assert(_symbols[symbol.id] == symbol);
+ final symbolLatLng =
+ await MapboxGlPlatform.getInstance(_id).getSymbolLatLng(symbol);
notifyListeners();
+ return symbolLatLng;
}
/// Removes the specified [symbol] from the map. The symbol must be a current
@@ -358,8 +375,18 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes once listeners have been notified.
Future removeSymbol(Symbol symbol) async {
assert(symbol != null);
- assert(_symbols[symbol._id] == symbol);
- await _removeSymbol(symbol._id);
+ assert(_symbols[symbol.id] == symbol);
+ await _removeSymbols([symbol.id]);
+ notifyListeners();
+ }
+
+ Future removeSymbols(Iterable symbols) async {
+ assert(symbols.length > 0);
+ symbols.forEach((s) {
+ assert(_symbols[s.id] == s);
+ });
+
+ await _removeSymbols(symbols.map((s) => s.id));
notifyListeners();
}
@@ -372,9 +399,7 @@ class MapboxMapController extends ChangeNotifier {
Future clearSymbols() async {
assert(_symbols != null);
final List symbolIds = List.from(_symbols.keys);
- for (String id in symbolIds) {
- await _removeSymbol(id);
- }
+ _removeSymbols(symbolIds);
notifyListeners();
}
@@ -383,11 +408,9 @@ class MapboxMapController extends ChangeNotifier {
///
/// The returned [Future] completes once the symbol has been removed from
/// [_symbols].
- Future _removeSymbol(String id) async {
- await _channel.invokeMethod('symbol#remove', {
- 'symbol': id,
- });
- _symbols.remove(id);
+ Future _removeSymbols(Iterable ids) async {
+ await MapboxGlPlatform.getInstance(_id).removeSymbols(ids);
+ _symbols.removeWhere((k, s) => ids.contains(k));
}
/// Adds a line to the map, configured using the specified custom [options].
@@ -400,14 +423,9 @@ class MapboxMapController extends ChangeNotifier {
Future addLine(LineOptions options, [Map data]) async {
final LineOptions effectiveOptions =
LineOptions.defaultOptions.copyWith(options);
- final String lineId = await _channel.invokeMethod(
- 'line#add',
- {
- 'options': effectiveOptions._toJson(),
- },
- );
- final Line line = Line(lineId, effectiveOptions, data);
- _lines[lineId] = line;
+ final line =
+ await MapboxGlPlatform.getInstance(_id).addLine(effectiveOptions);
+ _lines[line.id] = line;
notifyListeners();
return line;
}
@@ -421,14 +439,23 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes once listeners have been notified.
Future updateLine(Line line, LineOptions changes) async {
assert(line != null);
- assert(_lines[line._id] == line);
+ assert(_lines[line.id] == line);
assert(changes != null);
- await _channel.invokeMethod('line#update', {
- 'line': line._id,
- 'options': changes._toJson(),
- });
- line._options = line._options.copyWith(changes);
+ await MapboxGlPlatform.getInstance(_id).updateLine(line, changes);
+ line.options = line.options.copyWith(changes);
+ notifyListeners();
+ }
+
+ /// Retrieves the current position of the line.
+ /// This may be different from the value of `line.options.geometry` if the line is draggable.
+ /// In that case this method provides the line's actual position, and `line.options.geometry` the last programmatically set position.
+ Future> getLineLatLngs(Line line) async {
+ assert(line != null);
+ assert(_lines[line.id] == line);
+ final lineLatLngs =
+ await MapboxGlPlatform.getInstance(_id).getLineLatLngs(line);
notifyListeners();
+ return lineLatLngs;
}
/// Removes the specified [line] from the map. The line must be a current
@@ -440,8 +467,8 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes once listeners have been notified.
Future removeLine(Line line) async {
assert(line != null);
- assert(_lines[line._id] == line);
- await _removeLine(line._id);
+ assert(_lines[line.id] == line);
+ await _removeLine(line.id);
notifyListeners();
}
@@ -466,9 +493,7 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes once the line has been removed from
/// [_lines].
Future _removeLine(String id) async {
- await _channel.invokeMethod('line#remove', {
- 'line': id,
- });
+ await MapboxGlPlatform.getInstance(_id).removeLine(id);
_lines.remove(id);
}
@@ -482,14 +507,9 @@ class MapboxMapController extends ChangeNotifier {
Future addCircle(CircleOptions options, [Map data]) async {
final CircleOptions effectiveOptions =
CircleOptions.defaultOptions.copyWith(options);
- final String circleId = await _channel.invokeMethod(
- 'circle#add',
- {
- 'options': effectiveOptions._toJson(),
- },
- );
- final Circle circle = Circle(circleId, effectiveOptions, data);
- _circles[circleId] = circle;
+ final circle =
+ await MapboxGlPlatform.getInstance(_id).addCircle(effectiveOptions);
+ _circles[circle.id] = circle;
notifyListeners();
return circle;
}
@@ -503,28 +523,21 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes once listeners have been notified.
Future updateCircle(Circle circle, CircleOptions changes) async {
assert(circle != null);
- assert(_circles[circle._id] == circle);
+ assert(_circles[circle.id] == circle);
assert(changes != null);
- await _channel.invokeMethod('circle#update', {
- 'circle': circle._id,
- 'options': changes._toJson(),
- });
- circle._options = circle._options.copyWith(changes);
+ await MapboxGlPlatform.getInstance(_id).updateCircle(circle, changes);
+ circle.options = circle.options.copyWith(changes);
notifyListeners();
}
- /// `circle.options.geometry` can't get real-time location.For example, when you
- /// set circle `draggable` is true,and you dragged circle.At this time you
- /// should use `getCircleLatLng()`
+ /// Retrieves the current position of the circle.
+ /// This may be different from the value of `circle.options.geometry` if the circle is draggable.
+ /// In that case this method provides the circle's actual position, and `circle.options.geometry` the last programmatically set position.
Future getCircleLatLng(Circle circle) async {
assert(circle != null);
- assert(_circles[circle._id] == circle);
- Map mapLatLng =
- await _channel.invokeMethod('circle#getGeometry', {
- 'circle': circle._id,
- });
- LatLng circleLatLng =
- new LatLng(mapLatLng['latitude'], mapLatLng['longitude']);
+ assert(_circles[circle.id] == circle);
+ final circleLatLng =
+ await MapboxGlPlatform.getInstance(_id).getCircleLatLng(circle);
notifyListeners();
return circleLatLng;
}
@@ -538,8 +551,8 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes once listeners have been notified.
Future removeCircle(Circle circle) async {
assert(circle != null);
- assert(_circles[circle._id] == circle);
- await _removeCircle(circle._id);
+ assert(_circles[circle.id] == circle);
+ await _removeCircle(circle.id);
notifyListeners();
}
@@ -564,96 +577,97 @@ class MapboxMapController extends ChangeNotifier {
/// The returned [Future] completes once the circle has been removed from
/// [_circles].
Future _removeCircle(String id) async {
- await _channel.invokeMethod('circle#remove', {
- 'circle': id,
- });
+ await MapboxGlPlatform.getInstance(_id).removeCircle(id);
+
_circles.remove(id);
}
Future queryRenderedFeatures(
- Point point, List layerIds, String filter) async {
- try {
- final Map reply = await _channel.invokeMethod(
- 'map#queryRenderedFeatures',
- {
- 'x': point.x,
- 'y': point.y,
- 'layerIds': layerIds,
- 'filter': filter,
- },
- );
- return reply['features'];
- } on PlatformException catch (e) {
- return new Future.error(e);
- }
+ Point point, List layerIds, List filter) async {
+ return MapboxGlPlatform.getInstance(_id)
+ .queryRenderedFeatures(point, layerIds, filter);
}
Future queryRenderedFeaturesInRect(
Rect rect, List layerIds, String filter) async {
- try {
- final Map reply = await _channel.invokeMethod(
- 'map#queryRenderedFeatures',
- {
- 'left': rect.left,
- 'top': rect.top,
- 'right': rect.right,
- 'bottom': rect.bottom,
- 'layerIds': layerIds,
- 'filter': filter,
- },
- );
- return reply['features'];
- } on PlatformException catch (e) {
- return new Future.error(e);
- }
+ return MapboxGlPlatform.getInstance(_id)
+ .queryRenderedFeaturesInRect(rect, layerIds, filter);
}
-
Future invalidateAmbientCache() async {
- try {
- await _channel.invokeMethod('map#invalidateAmbientCache');
- return null;
- } on PlatformException catch (e) {
- return new Future.error(e);
- }
+ return MapboxGlPlatform.getInstance(_id).invalidateAmbientCache();
}
/// Get last my location
///
/// Return last latlng, nullable
-
Future requestMyLocationLatLng() async {
- try {
- final Map reply = await _channel.invokeMethod('locationComponent#getLastLocation', null);
- double latitude = 0.0, longitude = 0.0;
- if (reply.containsKey("latitude") && reply["latitude"] != null) {
- latitude = double.parse(reply["latitude"].toString());
- }
- if (reply.containsKey("longitude") && reply["longitude"] != null) {
- longitude = double.parse(reply["longitude"].toString());
- }
- return LatLng(latitude, longitude);
- } on PlatformException catch (e) {
- return new Future.error(e);
- }
- }
-
- ///This method returns the boundaries of the region currently displayed in the map.
- Future getVisibleRegion() async{
- try {
- final Map reply = await _channel.invokeMethod('map#getVisibleRegion', null);
- LatLng southwest, northeast;
- if (reply.containsKey("sw")) {
- List coordinates = reply["sw"];
- southwest = LatLng(coordinates[0], coordinates[1]);
- }
- if (reply.containsKey("ne")) {
- List coordinates = reply["ne"];
- northeast = LatLng(coordinates[0], coordinates[1]);
- }
- return LatLngBounds(southwest: southwest, northeast: northeast);
- } on PlatformException catch (e) {
- return new Future.error(e);
- }
+ return MapboxGlPlatform.getInstance(_id).requestMyLocationLatLng();
+ }
+
+ /// This method returns the boundaries of the region currently displayed in the map.
+ Future getVisibleRegion() async {
+ return MapboxGlPlatform.getInstance(_id).getVisibleRegion();
+ }
+
+ /// Adds an image to the style currently displayed in the map, so that it can later be referred to by the provided name.
+ ///
+ /// This allows you to add an image to the currently displayed style once, and from there on refer to it e.g. in the [Symbol.iconImage] anytime you add a [Symbol] later on.
+ /// Set [sdf] to true if the image you add is an SDF image.
+ /// Returns after the image has successfully been added to the style.
+ /// Note: This can only be called after OnStyleLoadedCallback has been invoked and any added images will have to be re-added if a new style is loaded.
+ ///
+ /// Example: Adding an asset image and using it in a new symbol:
+ /// ```dart
+ /// Future addImageFromAsset() async{
+ /// final ByteData bytes = await rootBundle.load("assets/someAssetImage.jpg");
+ /// final Uint8List list = bytes.buffer.asUint8List();
+ /// await controller.addImage("assetImage", list);
+ /// controller.addSymbol(
+ /// SymbolOptions(
+ /// geometry: LatLng(0,0),
+ /// iconImage: "assetImage",
+ /// ),
+ /// );
+ /// }
+ /// ```
+ ///
+ /// Example: Adding a network image (with the http package) and using it in a new symbol:
+ /// ```dart
+ /// Future addImageFromUrl() async{
+ /// var response = await get("https://example.com/image.png");
+ /// await controller.addImage("testImage", response.bodyBytes);
+ /// controller.addSymbol(
+ /// SymbolOptions(
+ /// geometry: LatLng(0,0),
+ /// iconImage: "testImage",
+ /// ),
+ /// );
+ /// }
+ /// ```
+ Future addImage(String name, Uint8List bytes, [bool sdf = false]) {
+ return MapboxGlPlatform.getInstance(_id).addImage(name, bytes, sdf);
+ }
+
+ /// For more information on what this does, see https://docs.mapbox.com/help/troubleshooting/optimize-map-label-placement/#label-collision
+ Future setSymbolIconAllowOverlap(bool enable) async {
+ await MapboxGlPlatform.getInstance(_id).setSymbolIconAllowOverlap(enable);
+ }
+
+ /// For more information on what this does, see https://docs.mapbox.com/help/troubleshooting/optimize-map-label-placement/#label-collision
+ Future setSymbolIconIgnorePlacement(bool enable) async {
+ await MapboxGlPlatform.getInstance(_id)
+ .setSymbolIconIgnorePlacement(enable);
+ }
+
+ /// For more information on what this does, see https://docs.mapbox.com/help/troubleshooting/optimize-map-label-placement/#label-collision
+ Future setSymbolTextAllowOverlap(bool enable) async {
+ await MapboxGlPlatform.getInstance(_id).setSymbolTextAllowOverlap(enable);
+ }
+
+ /// For more information on what this does, see https://docs.mapbox.com/help/troubleshooting/optimize-map-label-placement/#label-collision
+ Future setSymbolTextIgnorePlacement(bool enable) async {
+ await MapboxGlPlatform.getInstance(_id)
+ .setSymbolTextIgnorePlacement(enable);
}
}
diff --git a/lib/src/mapbox_map.dart b/lib/src/mapbox_map.dart
index 6cf587667..1a765a848 100644
--- a/lib/src/mapbox_map.dart
+++ b/lib/src/mapbox_map.dart
@@ -9,6 +9,7 @@ typedef void MapCreatedCallback(MapboxMapController controller);
class MapboxMap extends StatefulWidget {
const MapboxMap({
@required this.initialCameraPosition,
+ this.accessToken,
this.onMapCreated,
this.onStyleLoadedCallback,
this.gestureRecognizers,
@@ -22,19 +23,33 @@ class MapboxMap extends StatefulWidget {
this.tiltGesturesEnabled = true,
this.trackCameraPosition = false,
this.myLocationEnabled = false,
- this.myLocationTrackingMode = MyLocationTrackingMode.Tracking,
+ this.myLocationTrackingMode = MyLocationTrackingMode.None,
this.myLocationRenderMode = MyLocationRenderMode.COMPASS,
this.logoViewMargins,
this.compassViewPosition,
this.compassViewMargins,
this.attributionButtonMargins,
this.onMapClick,
+ this.onMapLongClick,
this.onCameraTrackingDismissed,
this.onCameraTrackingChanged,
+ this.onCameraIdle,
this.onMapIdle,
}) : assert(initialCameraPosition != null);
+
+ /// If you want to use Mapbox hosted styles and map tiles, you need to provide a Mapbox access token.
+ /// Obtain a free access token on [your Mapbox account page](https://www.mapbox.com/account/access-tokens/).
+ /// The reccommended way is to use this parameter to set your access token, an alternative way to add your access tokens through external files is described in the plugin's wiki on Github.
+ ///
+ /// Note: You should not use this parameter AND set the access token through external files at the same time, and you should use the same token throughout the entire app.
+ final String accessToken;
+
+ /// Please note: you should only add annotations (e.g. symbols or circles) after `onStyleLoadedCallback` has been called.
final MapCreatedCallback onMapCreated;
+
+ /// Called when the map style has been successfully loaded and the annotation managers have been enabled.
+ /// Please note: you should only add annotations (e.g. symbols or circles) after this callback has been called.
final OnStyleLoadedCallback onStyleLoadedCallback;
/// The initial position of the map's camera.
@@ -68,7 +83,10 @@ class MapboxMap extends StatefulWidget {
/// True if the map view should respond to tilt gestures.
final bool tiltGesturesEnabled;
- /// True if the map view should relay camera move events to Flutter.
+ /// True if you want to be notified of map camera movements by the MapboxMapController. Default is false.
+ ///
+ /// If this is set to true and the user pans/zooms/rotates the map, MapboxMapController (which is a ChangeNotifier)
+ /// will notify it's listeners and you can then get the new MapboxMapController.cameraPosition.
final bool trackCameraPosition;
/// True if a "My Location" layer should be shown on the map.
@@ -96,7 +114,7 @@ class MapboxMap extends StatefulWidget {
/// when the map tries to turn on the My Location layer.
final bool myLocationEnabled;
- /// The mode used to track the user location on the map
+ /// The mode used to let the map's camera follow the device's physical location
final MyLocationTrackingMode myLocationTrackingMode;
/// The mode to render the user location symbol
@@ -126,11 +144,17 @@ class MapboxMap extends StatefulWidget {
final Set> gestureRecognizers;
final OnMapClickCallback onMapClick;
+ final OnMapClickCallback onMapLongClick;
- /// Called when the location tracking mode changes, such as when the user moves the map
+ /// Called when the map's camera no longer follows the physical device location, e.g. because the user moved the map
final OnCameraTrackingDismissedCallback onCameraTrackingDismissed;
+
+ /// Called when the location tracking mode changes
final OnCameraTrackingChangedCallback onCameraTrackingChanged;
+ // Called when camera movement has ended.
+ final OnCameraIdleCallback onCameraIdle;
+
/// Called when map view is entering an idle state, and no more drawing will
/// be necessary until new data is loaded or there is some interaction with
/// the map.
@@ -148,33 +172,17 @@ class _MapboxMapState extends State {
Completer();
_MapboxMapOptions _mapboxMapOptions;
+ final MapboxGlPlatform _mapboxGlPlatform = MapboxGlPlatform.createInstance();
@override
Widget build(BuildContext context) {
final Map creationParams = {
- 'initialCameraPosition': widget.initialCameraPosition?._toMap(),
+ 'initialCameraPosition': widget.initialCameraPosition?.toMap(),
'options': _MapboxMapOptions.fromWidget(widget).toMap(),
+ 'accessToken': widget.accessToken,
};
- if (defaultTargetPlatform == TargetPlatform.android) {
- return AndroidView(
- viewType: 'plugins.flutter.io/mapbox_gl',
- onPlatformViewCreated: onPlatformViewCreated,
- gestureRecognizers: widget.gestureRecognizers,
- creationParams: creationParams,
- creationParamsCodec: const StandardMessageCodec(),
- );
- } else if (defaultTargetPlatform == TargetPlatform.iOS) {
- return UiKitView(
- viewType: 'plugins.flutter.io/mapbox_gl',
- onPlatformViewCreated: onPlatformViewCreated,
- gestureRecognizers: widget.gestureRecognizers,
- creationParams: creationParams,
- creationParamsCodec: const StandardMessageCodec(),
- );
- }
-
- return Text(
- '$defaultTargetPlatform is not yet supported by the maps plugin');
+ return _mapboxGlPlatform.buildView(
+ creationParams, onPlatformViewCreated, widget.gestureRecognizers);
}
@override
@@ -202,12 +210,15 @@ class _MapboxMapState extends State {
}
Future onPlatformViewCreated(int id) async {
+ MapboxGlPlatform.addInstance(id, _mapboxGlPlatform);
final MapboxMapController controller = await MapboxMapController.init(
id, widget.initialCameraPosition,
onStyleLoadedCallback: widget.onStyleLoadedCallback,
onMapClick: widget.onMapClick,
+ onMapLongClick: widget.onMapLongClick,
onCameraTrackingDismissed: widget.onCameraTrackingDismissed,
onCameraTrackingChanged: widget.onCameraTrackingChanged,
+ onCameraIdle: widget.onCameraIdle,
onMapIdle: widget.onMapIdle);
_controller.complete(controller);
if (widget.onMapCreated != null) {
@@ -257,7 +268,7 @@ class _MapboxMapOptions {
logoViewMargins: map.logoViewMargins,
compassViewPosition: map.compassViewPosition,
compassViewMargins: map.compassViewMargins,
- attributionButtonMargins: map.attributionButtonMargins
+ attributionButtonMargins: map.attributionButtonMargins,
);
}
@@ -311,9 +322,9 @@ class _MapboxMapOptions {
}
addIfNonNull('compassEnabled', compassEnabled);
- addIfNonNull('cameraTargetBounds', cameraTargetBounds?._toJson());
+ addIfNonNull('cameraTargetBounds', cameraTargetBounds?.toJson());
addIfNonNull('styleString', styleString);
- addIfNonNull('minMaxZoomPreference', minMaxZoomPreference?._toJson());
+ addIfNonNull('minMaxZoomPreference', minMaxZoomPreference?.toJson());
addIfNonNull('rotateGesturesEnabled', rotateGesturesEnabled);
addIfNonNull('scrollGesturesEnabled', scrollGesturesEnabled);
addIfNonNull('tiltGesturesEnabled', tiltGesturesEnabled);
@@ -325,12 +336,15 @@ class _MapboxMapOptions {
addIfNonNull('logoViewMargins', pointToArray(logoViewMargins));
addIfNonNull('compassViewPosition', compassViewPosition?.index);
addIfNonNull('compassViewMargins', pointToArray(compassViewMargins));
- addIfNonNull('attributionButtonMargins', pointToArray(attributionButtonMargins));
+ addIfNonNull(
+ 'attributionButtonMargins', pointToArray(attributionButtonMargins));
return optionsMap;
}
Map updatesMap(_MapboxMapOptions newOptions) {
final Map prevOptionsMap = toMap();
- return newOptions.toMap()..removeWhere((String key, dynamic value) => prevOptionsMap[key] == value);
+ return newOptions.toMap()
+ ..removeWhere(
+ (String key, dynamic value) => prevOptionsMap[key] == value);
}
}
diff --git a/mapbox_gl_platform_interface/CHANGELOG.md b/mapbox_gl_platform_interface/CHANGELOG.md
new file mode 100644
index 000000000..c15887ba4
--- /dev/null
+++ b/mapbox_gl_platform_interface/CHANGELOG.md
@@ -0,0 +1,2 @@
+## 0.7.0
+- Initial version
\ No newline at end of file
diff --git a/mapbox_gl_platform_interface/LICENSE b/mapbox_gl_platform_interface/LICENSE
new file mode 100644
index 000000000..a4c4948f4
--- /dev/null
+++ b/mapbox_gl_platform_interface/LICENSE
@@ -0,0 +1,6 @@
+flutter-mapbox-gl copyright (c) 2018, Mapbox.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/mapbox_gl_platform_interface/README.md b/mapbox_gl_platform_interface/README.md
new file mode 100644
index 000000000..f3e2910f0
--- /dev/null
+++ b/mapbox_gl_platform_interface/README.md
@@ -0,0 +1 @@
+Contains the web platform implementation for the [Flutter Mapbox GL plugin](https://github.com/tobrun/flutter-mapbox-gl).
\ No newline at end of file
diff --git a/mapbox_gl_platform_interface/lib/mapbox_gl_platform_interface.dart b/mapbox_gl_platform_interface/lib/mapbox_gl_platform_interface.dart
new file mode 100644
index 000000000..0abe3163a
--- /dev/null
+++ b/mapbox_gl_platform_interface/lib/mapbox_gl_platform_interface.dart
@@ -0,0 +1,19 @@
+library mapbox_gl_platform_interface;
+
+import 'dart:math';
+import 'dart:typed_data';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:meta/meta.dart' show required, visibleForTesting;
+
+part 'src/callbacks.dart';
+part 'src/camera.dart';
+part 'src/circle.dart';
+part 'src/line.dart';
+part 'src/location.dart';
+part 'src/method_channel_mapbox_gl.dart';
+part 'src/symbol.dart';
+part 'src/ui.dart';
+part 'src/mapbox_gl_platform_interface.dart';
diff --git a/lib/src/callbacks.dart b/mapbox_gl_platform_interface/lib/src/callbacks.dart
similarity index 97%
rename from lib/src/callbacks.dart
rename to mapbox_gl_platform_interface/lib/src/callbacks.dart
index 85d746a82..e375f2fef 100644
--- a/lib/src/callbacks.dart
+++ b/mapbox_gl_platform_interface/lib/src/callbacks.dart
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-part of mapbox_gl;
+part of mapbox_gl_platform_interface;
/// Callback function taking a single argument.
typedef void ArgumentCallback(T argument);
diff --git a/lib/src/camera.dart b/mapbox_gl_platform_interface/lib/src/camera.dart
similarity index 94%
rename from lib/src/camera.dart
rename to mapbox_gl_platform_interface/lib/src/camera.dart
index d6b407433..747086ddf 100644
--- a/lib/src/camera.dart
+++ b/mapbox_gl_platform_interface/lib/src/camera.dart
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-part of mapbox_gl;
+part of mapbox_gl_platform_interface;
/// The position of the map "camera", the view point from which the world is
/// shown in the map view. Aggregates the camera's [target] geographical
@@ -51,9 +51,9 @@ class CameraPosition {
/// will be silently clamped to the supported range.
final double zoom;
- dynamic _toMap() => {
+ dynamic toMap() => {
'bearing': bearing,
- 'target': target._toJson(),
+ 'target': target.toJson(),
'tilt': tilt,
'zoom': zoom,
};
@@ -98,14 +98,14 @@ class CameraUpdate {
/// Returns a camera update that moves the camera to the specified position.
static CameraUpdate newCameraPosition(CameraPosition cameraPosition) {
return CameraUpdate._(
- ['newCameraPosition', cameraPosition._toMap()],
+ ['newCameraPosition', cameraPosition.toMap()],
);
}
/// Returns a camera update that moves the camera target to the specified
/// geographical location.
static CameraUpdate newLatLng(LatLng latLng) {
- return CameraUpdate._(['newLatLng', latLng._toJson()]);
+ return CameraUpdate._(['newLatLng', latLng.toJson()]);
}
/// Returns a camera update that transforms the camera so that the specified
@@ -115,7 +115,7 @@ class CameraUpdate {
static CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) {
return CameraUpdate._([
'newLatLngBounds',
- bounds._toList(),
+ bounds.toList(),
padding,
]);
}
@@ -124,7 +124,7 @@ class CameraUpdate {
/// geographical location and zoom level.
static CameraUpdate newLatLngZoom(LatLng latLng, double zoom) {
return CameraUpdate._(
- ['newLatLngZoom', latLng._toJson(), zoom],
+ ['newLatLngZoom', latLng.toJson(), zoom],
);
}
@@ -180,7 +180,7 @@ class CameraUpdate {
static CameraUpdate bearingTo(double bearing) {
return CameraUpdate._(['bearingTo', bearing]);
}
-
+
/// Returns a camera update that sets the camera bearing.
static CameraUpdate tiltTo(double tilt) {
return CameraUpdate._(['tiltTo', tilt]);
@@ -188,5 +188,5 @@ class CameraUpdate {
final dynamic _json;
- dynamic _toJson() => _json;
+ dynamic toJson() => _json;
}
diff --git a/lib/src/circle.dart b/mapbox_gl_platform_interface/lib/src/circle.dart
similarity index 92%
rename from lib/src/circle.dart
rename to mapbox_gl_platform_interface/lib/src/circle.dart
index 9d738f267..01815ae85 100644
--- a/lib/src/circle.dart
+++ b/mapbox_gl_platform_interface/lib/src/circle.dart
@@ -4,29 +4,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-part of mapbox_gl;
+part of mapbox_gl_platform_interface;
class Circle {
- @visibleForTesting
- Circle(this._id, this._options, [this._data]);
+ Circle(this._id, this.options, [this._data]);
/// A unique identifier for this circle.
///
/// The identifier is an arbitrary unique string.
final String _id;
String get id => _id;
-
-
- CircleOptions _options;
final Map _data;
Map get data => _data;
+
/// The circle configuration options most recently applied programmatically
/// via the map controller.
///
/// The returned value does not reflect any changes made to the circle through
/// touch events. Add listeners to the owning map controller to track those.
- CircleOptions get options => _options;
+ CircleOptions options;
}
/// Configuration options for [Circle] instances.
@@ -79,7 +76,7 @@ class CircleOptions {
);
}
- dynamic _toJson() {
+ dynamic toJson() {
final Map json = {};
void addIfPresent(String fieldName, dynamic value) {
@@ -95,7 +92,7 @@ class CircleOptions {
addIfPresent('circleStrokeWidth', circleStrokeWidth);
addIfPresent('circleStrokeColor', circleStrokeColor);
addIfPresent('circleStrokeOpacity', circleStrokeOpacity);
- addIfPresent('geometry', geometry?._toJson());
+ addIfPresent('geometry', geometry?.toJson());
addIfPresent('draggable', draggable);
return json;
}
diff --git a/lib/src/line.dart b/mapbox_gl_platform_interface/lib/src/line.dart
similarity index 91%
rename from lib/src/line.dart
rename to mapbox_gl_platform_interface/lib/src/line.dart
index 0832f9bd4..376ac1f78 100644
--- a/lib/src/line.dart
+++ b/mapbox_gl_platform_interface/lib/src/line.dart
@@ -4,11 +4,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-part of mapbox_gl;
+part of mapbox_gl_platform_interface;
class Line {
- @visibleForTesting
- Line(this._id, this._options, [this._data]);
+ Line(this._id, this.options, [this._data]);
/// A unique identifier for this line.
///
@@ -18,17 +17,15 @@ class Line {
String get id => _id;
final Map _data;
-
- Map get data => _data;
- LineOptions _options;
+ Map get data => _data;
/// The line configuration options most recently applied programmatically
/// via the map controller.
///
/// The returned value does not reflect any changes made to the line through
/// touch events. Add listeners to the owning map controller to track those.
- LineOptions get options => _options;
+ LineOptions options;
}
/// Configuration options for [Line] instances.
@@ -84,7 +81,7 @@ class LineOptions {
);
}
- dynamic _toJson() {
+ dynamic toJson() {
final Map json = {};
void addIfPresent(String fieldName, dynamic value) {
@@ -101,7 +98,8 @@ class LineOptions {
addIfPresent('lineOffset', lineOffset);
addIfPresent('lineBlur', lineBlur);
addIfPresent('linePattern', linePattern);
- addIfPresent('geometry', geometry?.map((LatLng latLng) => latLng._toJson())?.toList());
+ addIfPresent('geometry',
+ geometry?.map((LatLng latLng) => latLng.toJson())?.toList());
addIfPresent('draggable', draggable);
return json;
}
diff --git a/lib/src/location.dart b/mapbox_gl_platform_interface/lib/src/location.dart
similarity index 95%
rename from lib/src/location.dart
rename to mapbox_gl_platform_interface/lib/src/location.dart
index 4f33b7b49..617943453 100644
--- a/lib/src/location.dart
+++ b/mapbox_gl_platform_interface/lib/src/location.dart
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-part of mapbox_gl;
+part of mapbox_gl_platform_interface;
/// A pair of latitude and longitude coordinates, stored as degrees.
class LatLng {
@@ -26,7 +26,7 @@ class LatLng {
/// The longitude in degrees between -180.0 (inclusive) and 180.0 (exclusive).
final double longitude;
- dynamic _toJson() {
+ dynamic toJson() {
return [latitude, longitude];
}
@@ -73,8 +73,8 @@ class LatLngBounds {
/// The northeast corner of the rectangle.
final LatLng northeast;
- dynamic _toList() {
- return [southwest._toJson(), northeast._toJson()];
+ dynamic toList() {
+ return [southwest.toJson(), northeast.toJson()];
}
@visibleForTesting
diff --git a/mapbox_gl_platform_interface/lib/src/mapbox_gl_platform_interface.dart b/mapbox_gl_platform_interface/lib/src/mapbox_gl_platform_interface.dart
new file mode 100644
index 000000000..da022c739
--- /dev/null
+++ b/mapbox_gl_platform_interface/lib/src/mapbox_gl_platform_interface.dart
@@ -0,0 +1,213 @@
+// ignore_for_file: unnecessary_getters_setters
+
+part of mapbox_gl_platform_interface;
+
+abstract class MapboxGlPlatform {
+ /// The default instance of [MapboxGlPlatform] to use.
+ ///
+ /// Defaults to [MethodChannelMapboxGl].
+ ///
+ /// Platform-specific plugins should set this with their own platform-specific
+ /// class that extends [MapboxGlPlatform] when they register themselves.
+ static MapboxGlPlatform Function() createInstance =
+ () => MethodChannelMapboxGl();
+
+ static Map _instances = {};
+
+ static void addInstance(int id, MapboxGlPlatform platform) {
+ _instances[id] = platform;
+ }
+
+ static MapboxGlPlatform getInstance(int id) {
+ return _instances[id];
+ }
+
+ final ArgumentCallbacks onInfoWindowTappedPlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onSymbolTappedPlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onLineTappedPlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onCircleTappedPlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onCameraMoveStartedPlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onCameraMovePlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onCameraIdlePlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onMapStyleLoadedPlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks> onMapClickPlatform =
+ ArgumentCallbacks>();
+
+ final ArgumentCallbacks> onMapLongClickPlatform =
+ ArgumentCallbacks>();
+
+ final ArgumentCallbacks
+ onCameraTrackingChangedPlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onCameraTrackingDismissedPlatform =
+ ArgumentCallbacks();
+
+ final ArgumentCallbacks onMapIdlePlatform = ArgumentCallbacks();
+
+ Future initPlatform(int id) async {
+ throw UnimplementedError('initPlatform() has not been implemented.');
+ }
+
+ Widget buildView(
+ Map creationParams,
+ Function onPlatformViewCreated,
+ Set> gestureRecognizers) {
+ throw UnimplementedError('buildView() has not been implemented.');
+ }
+
+ Future updateMapOptions(
+ Map optionsUpdate) async {
+ throw UnimplementedError('updateMapOptions() has not been implemented.');
+ }
+
+ Future animateCamera(CameraUpdate cameraUpdate) async {
+ throw UnimplementedError('animateCamera() has not been implemented.');
+ }
+
+ Future moveCamera(CameraUpdate cameraUpdate) async {
+ throw UnimplementedError('moveCamera() has not been implemented.');
+ }
+
+ Future updateMyLocationTrackingMode(
+ MyLocationTrackingMode myLocationTrackingMode) async {
+ throw UnimplementedError(
+ 'updateMyLocationTrackingMode() has not been implemented.');
+ }
+
+ Future matchMapLanguageWithDeviceDefault() async {
+ throw UnimplementedError(
+ 'matchMapLanguageWithDeviceDefault() has not been implemented.');
+ }
+
+ Future updateContentInsets(EdgeInsets insets, bool animated) async {
+ throw UnimplementedError('updateContentInsets() has not been implemented.');
+ }
+
+ Future