├── .fvmrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── publish.yml ├── .gitignore ├── .metadata ├── LICENSE ├── README.md ├── melos.yaml ├── packages ├── platform_maps_flutter │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── example │ │ ├── .gitignore │ │ ├── .metadata │ │ ├── README.md │ │ ├── analysis_options.yaml │ │ ├── android │ │ │ ├── .gitignore │ │ │ ├── .project │ │ │ ├── app │ │ │ │ ├── .project │ │ │ │ ├── build.gradle │ │ │ │ └── src │ │ │ │ │ ├── debug │ │ │ │ │ └── AndroidManifest.xml │ │ │ │ │ ├── main │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ ├── kotlin │ │ │ │ │ │ └── com │ │ │ │ │ │ │ └── example │ │ │ │ │ │ │ └── flutter_platform_maps_example │ │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ │ └── res │ │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ │ │ └── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── profile │ │ │ │ │ └── AndroidManifest.xml │ │ │ ├── build.gradle │ │ │ ├── gradle.properties │ │ │ ├── gradle │ │ │ │ └── wrapper │ │ │ │ │ └── gradle-wrapper.properties │ │ │ └── settings.gradle │ │ ├── ios │ │ │ ├── .gitignore │ │ │ ├── Flutter │ │ │ │ ├── AppFrameworkInfo.plist │ │ │ │ ├── Debug.xcconfig │ │ │ │ └── Release.xcconfig │ │ │ ├── Podfile │ │ │ ├── Podfile.lock │ │ │ ├── Runner.xcodeproj │ │ │ │ ├── project.pbxproj │ │ │ │ ├── project.xcworkspace │ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ │ └── xcshareddata │ │ │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ │ └── xcshareddata │ │ │ │ │ └── xcschemes │ │ │ │ │ └── Runner.xcscheme │ │ │ ├── Runner.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ └── Runner │ │ │ │ ├── AppDelegate.swift │ │ │ │ ├── Assets.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ │ └── LaunchImage.imageset │ │ │ │ │ ├── Contents.json │ │ │ │ │ ├── LaunchImage.png │ │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ │ └── README.md │ │ │ │ ├── Base.lproj │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ │ ├── Info.plist │ │ │ │ └── Runner-Bridging-Header.h │ │ ├── lib │ │ │ └── main.dart │ │ └── pubspec.yaml │ ├── lib │ │ └── platform_maps_flutter.dart │ ├── pubspec.yaml │ └── test │ │ └── platform_maps_test.dart ├── platform_maps_flutter_apple │ ├── .gitignore │ ├── .metadata │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── platform_maps_flutter_apple.dart │ │ └── src │ │ │ ├── apple_maps_bitmap_descriptor.dart │ │ │ ├── apple_maps_camera_update.dart │ │ │ ├── apple_maps_platform_controller.dart │ │ │ ├── apple_maps_widget.dart │ │ │ └── mapper_extensions.dart │ ├── pubspec.yaml │ └── test │ │ └── platform_maps_flutter_apple_test.dart ├── platform_maps_flutter_google_android │ ├── .gitignore │ ├── .metadata │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ ├── platform_maps_flutter_google_android.dart │ │ └── src │ │ │ ├── google_map_original.dart │ │ │ ├── google_map_original │ │ │ ├── controller.dart │ │ │ └── google_map.dart │ │ │ ├── google_maps_bitmap_descriptor.dart │ │ │ ├── google_maps_camera_update.dart │ │ │ ├── google_maps_platform_controller.dart │ │ │ ├── google_maps_widget.dart │ │ │ └── mapper_extensions.dart │ ├── pubspec.yaml │ └── test │ │ └── platform_maps_flutter_google_android_test.dart └── platform_maps_flutter_platform_interface │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ ├── platform_maps_flutter_platform_interface.dart │ └── src │ │ ├── platform_bitmap_descriptor.dart │ │ ├── platform_camera_update.dart │ │ ├── platform_map.dart │ │ ├── platform_maps_platform.dart │ │ ├── platform_maps_platform_controller.dart │ │ ├── platform_maps_platform_widget.dart │ │ ├── types.dart │ │ └── types │ │ ├── bitmap.dart │ │ ├── callbacks.dart │ │ ├── camera_position.dart │ │ ├── camera_update.dart │ │ ├── cap.dart │ │ ├── circle.dart │ │ ├── controller.dart │ │ ├── info_window.dart │ │ ├── joint_type.dart │ │ ├── lat_lng.dart │ │ ├── map_type.dart │ │ ├── marker.dart │ │ ├── min_max_zoom_preference.dart │ │ ├── pattern_item.dart │ │ ├── platform_maps_platform_widget_creation_params.dart │ │ ├── polygon.dart │ │ └── polyline.dart │ ├── pubspec.yaml │ └── test │ └── platform_maps_flutter_platform_interface_test.dart └── pubspec.yaml /.fvmrc: -------------------------------------------------------------------------------- 1 | { 2 | "flutter": "3.19.6" 3 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: LuisThein 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Smartphone (please complete the following information):** 27 | - Device: [e.g. iPhone6] 28 | - Version [e.g. 22] 29 | 30 | **flutter doctor** 31 | Please add the `flutter doctor` output. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: LuisThein 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.* 2 | 3 | *List which issues are fixed by this PR.* 4 | 5 | ## Pre-launch Checklist 6 | 7 | - [ ] I updated pubspec.yaml with an appropriate new version according to the [pub versioning philosophy]. 8 | - [ ] I updated CHANGELOG.md to add a description of the change. 9 | - [ ] I updated/added relevant documentation (doc comments with `///`). 10 | - [ ] I added new tests to check the change I am making if a test is possible. 11 | - [ ] All existing and new tests are passing. -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | JAVA_VERSION: "17.x" 11 | JAVA_DISTRIBUTION: "zulu" 12 | 13 | jobs: 14 | build: 15 | runs-on: macos-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: actions/setup-java@v4 19 | with: 20 | java-version: ${{ env.JAVA_VERSION }} 21 | distribution: ${{ env.JAVA_DISTRIBUTION }} 22 | - uses: dart-lang/setup-dart@v1 23 | - name: Install fvm 24 | run: | 25 | dart pub global activate fvm 3.1.4 26 | fvm install 27 | - name: Install melos 28 | run: dart pub global activate melos 6.0.0 29 | - name: Install dependencies 30 | run: melos bs 31 | - name: Run dart analyze 32 | run: melos analyze 33 | - name: build iOS example project 34 | working-directory: ./packages/platform_maps_flutter/example 35 | run: fvm flutter build ios --release --no-codesign 36 | - name: build android example project 37 | working-directory: ./packages/platform_maps_flutter/example 38 | run: fvm flutter build apk 39 | # disabled for now, because will fail with multi-package setup 40 | # - name: publish --dry-run 41 | # run: flutter pub publish --dry-run 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | pubspec.lock 33 | 34 | # Android related 35 | **/android/**/gradle-wrapper.jar 36 | **/android/.gradle 37 | **/android/captures/ 38 | **/android/gradlew 39 | **/android/gradlew.bat 40 | **/android/local.properties 41 | **/android/**/GeneratedPluginRegistrant.java 42 | 43 | # iOS/XCode related 44 | **/ios/**/*.mode1v3 45 | **/ios/**/*.mode2v3 46 | **/ios/**/*.moved-aside 47 | **/ios/**/*.pbxuser 48 | **/ios/**/*.perspectivev3 49 | **/ios/**/*sync/ 50 | **/ios/**/.sconsign.dblite 51 | **/ios/**/.tags* 52 | **/ios/**/.vagrant/ 53 | **/ios/**/DerivedData/ 54 | **/ios/**/Icon? 55 | **/ios/**/Pods/ 56 | **/ios/**/.symlinks/ 57 | **/ios/**/profile 58 | **/ios/**/xcuserdata 59 | **/ios/.generated/ 60 | **/ios/Flutter/App.framework 61 | **/ios/Flutter/Flutter.framework 62 | **/ios/Flutter/Flutter.podspec 63 | **/ios/Flutter/Generated.xcconfig 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | 77 | # FVM Version Cache 78 | .fvm/ 79 | # Melos pubspec overrides 80 | pubspec_overrides.yaml 81 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2024, Albert Heijn Technology 4 | Copyright (c) 2019, Luis Thein 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # platform_maps_flutter 2 | 3 | A Flutter package that provides a native map to both Android and iOS devices. 4 | 5 | The plugin relies on Flutter's mechanism for embedding Android and iOS views. As that mechanism is currently in a developers preview, this plugin should also be considered a developers preview. 6 | 7 | This package combines the `google_maps_flutter` plugin with `apple_maps_flutter` to create a cross platform implementation of native maps for Android/iOS. 8 | 9 | # Screenshots 10 | 11 | | Android | iOS | 12 | | :-----------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------: | 13 | | ![Example 1](https://luisthein.de/flutter-platform-maps-images/android_screenshot1-min.png) | ![Example 2](https://luisthein.de/flutter-platform-maps-images/ios_screenshot1-min.png) | 14 | | ![Example 1](https://luisthein.de/flutter-platform-maps-images/android_screenshot2-min.png) | ![Example 2](https://luisthein.de/flutter-platform-maps-images/ios_screenshot2-min.png) | 15 | 16 | # Current functionality 17 | 18 | - Camera movement including bearing, heading, tilt (also animated) 19 | - Markers, including custom marker images and Info windows 20 | - Different map types 21 | - Map manipulation, enable/disable gestures, show current location, show compass ... 22 | 23 | 24 | # iOS 25 | 26 | You will have to add the key `Privacy - Location When In Use Usage Description` with the value of your usage description. 27 | 28 | # Android 29 | 30 | Specify your API key in the application manifest android/app/src/main/AndroidManifest.xml: 31 | 32 | ```xml 33 | 37 | ``` 38 | 39 | ## Sample Usage 40 | 41 | ```dart 42 | class HomePage extends StatelessWidget { 43 | @override 44 | Widget build(BuildContext context) { 45 | return Scaffold( 46 | body: PlatformMap( 47 | initialCameraPosition: CameraPosition( 48 | target: const LatLng(47.6, 8.8796), 49 | zoom: 16.0, 50 | ), 51 | markers: Set.of( 52 | [ 53 | Marker( 54 | markerId: MarkerId('marker_1'), 55 | position: LatLng(47.6, 8.8796), 56 | consumeTapEvents: true, 57 | infoWindow: InfoWindow( 58 | title: 'PlatformMarker', 59 | snippet: "Hi I'm a Platform Marker", 60 | ), 61 | onTap: () { 62 | print("Marker tapped"); 63 | }, 64 | ), 65 | ], 66 | ), 67 | myLocationEnabled: true, 68 | myLocationButtonEnabled: true, 69 | onTap: (location) => print('onTap: $location'), 70 | onCameraMove: (cameraUpdate) => print('onCameraMove: $cameraUpdate'), 71 | compassEnabled: true, 72 | onMapCreated: (controller) { 73 | Future.delayed(Duration(seconds: 2)).then( 74 | (_) { 75 | controller.animateCamera( 76 | CameraUpdate.newCameraPosition( 77 | const CameraPosition( 78 | bearing: 270.0, 79 | target: LatLng(51.5160895, -0.1294527), 80 | tilt: 30.0, 81 | zoom: 18, 82 | ), 83 | ), 84 | ); 85 | }, 86 | ); 87 | }, 88 | ), 89 | ); 90 | } 91 | } 92 | ``` 93 | 94 | Suggestions and PR's to make this plugin better are always welcome. Please notice that the features provided by this package depend on the apple_maps_flutter plugin, which will improve in the future. 95 | -------------------------------------------------------------------------------- /melos.yaml: -------------------------------------------------------------------------------- 1 | name: platform_maps_flutter 2 | 3 | sdkPath: .fvm/flutter_sdk 4 | 5 | packages: 6 | - packages/** 7 | 8 | scripts: 9 | dart_fix: > 10 | melos exec -c 1 --fail-fast --\ 11 | dart fix --apply -------------------------------------------------------------------------------- /packages/platform_maps_flutter/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.0.0-beta 2 | 3 | * Migrate to a federated plugin structure 4 | 5 | ## 1.0.2 6 | 7 | * Updates apple_maps_flutter to apply memory leak fix 8 | * makes it possible to take snapshots of the map 9 | 10 | ## 1.0.1 11 | 12 | * Adds `newLatLngBounds` to PlatformMapController 13 | 14 | ## 1.0.0 15 | 16 | * Adds null safety. Refresh example app (Tanks to @jonbhanson). 17 | 18 | ## 0.1.9+4 19 | 20 | * Fixed build failure 21 | 22 | ## 0.1.9+3 23 | 24 | * InfoWindow anchor is now configurable 25 | 26 | ## 0.1.9+2 27 | 28 | * Fixed placement of custom Markers 29 | 30 | ## 0.1.9+1 31 | 32 | * Updated apple_maps_flutter to fix infoWindow onTap 33 | 34 | ## 0.1.9 35 | 36 | * The Annotation rework of [commit](https://github.com/LuisThein/apple_maps_flutter/commit/01e3ea4f4a4274d4d2d2636fd863ba1e3283420d) from apple_maps_flutter was implemented 37 | * The methods showMarkerInfoWindow, hideMarkerInfoWindow and isMarkerInfoWindowShown were added 38 | * Scaling of custom markers now works the same way for ios and android 39 | * The method BitmapDescriptor.fromBytes was added 40 | 41 | ## 0.1.8+1 42 | 43 | * Updated apple_maps_flutter to solve issue #8 which caused an unresponsive map on iOS after calling setState. 44 | 45 | ## 0.1.8 46 | 47 | * Added zoomControlsEnabled flag for Google Maps 48 | 49 | ## 0.1.7 50 | 51 | * Fixed minor bugs 52 | 53 | ## 0.1.6 54 | 55 | * Added ability to place circles. 56 | 57 | ## 0.1.5 58 | 59 | * Added ability to place polygons. 60 | 61 | ## 0.1.4+5 62 | 63 | * Updated apple_maps_flutter version. 64 | 65 | ## 0.1.4+4 66 | 67 | * Fixed various build issues on android and iOS. 68 | 69 | ## 0.1.4+3 70 | 71 | * Updated image resource of README.md. 72 | 73 | ## 0.1.4+2 74 | 75 | * Fixed Marker icon types. 76 | 77 | ## 0.1.4+1 78 | 79 | * Fixed Marker icon Bug. 80 | 81 | ## 0.1.4 82 | 83 | * Added ability to place polylines. 84 | * Added ability to set padding to the map. 85 | 86 | ## 0.1.3 87 | 88 | * Updated apple_maps_flutter dependency, to fix a Marker Bug on iOS. 89 | 90 | ## 0.1.2 91 | 92 | * Added getter for visible map region. 93 | 94 | ## 0.1.1 95 | 96 | * Added an example. 97 | 98 | ## 0.1.0 99 | 100 | * Initial release. 101 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2024, Albert Heijn Technology 4 | Copyright (c) 2019, Luis Thein 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /packages/platform_maps_flutter/README.md: -------------------------------------------------------------------------------- 1 | # platform_maps_flutter 2 | 3 | A Flutter package that provides a native map to both Android and iOS devices. 4 | 5 | The plugin relies on Flutter's mechanism for embedding Android and iOS views. As that mechanism is currently in a developers preview, this plugin should also be considered a developers preview. 6 | 7 | This package combines the `google_maps_flutter` plugin with `apple_maps_flutter` to create a cross platform implementation of native maps for Android/iOS. 8 | 9 | # Screenshots 10 | 11 | | Android | iOS | 12 | | :-----------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------: | 13 | | ![Example 1](https://luisthein.de/flutter-platform-maps-images/android_screenshot1-min.png) | ![Example 2](https://luisthein.de/flutter-platform-maps-images/ios_screenshot1-min.png) | 14 | | ![Example 1](https://luisthein.de/flutter-platform-maps-images/android_screenshot2-min.png) | ![Example 2](https://luisthein.de/flutter-platform-maps-images/ios_screenshot2-min.png) | 15 | 16 | # Current functionality 17 | 18 | - Camera movement including bearing, heading, tilt (also animated) 19 | - Markers, including custom marker images and Info windows 20 | - Different map types 21 | - Map manipulation, enable/disable gestures, show current location, show compass ... 22 | 23 | 24 | # iOS 25 | 26 | To use this plugin on iOS you need to opt-in for the embedded views preview by adding a boolean property to the app's Info.plist file, with the key `io.flutter.embedded_views_preview` and the value `YES`. You will also have to add the key `Privacy - Location When In Use Usage Description` with the value of your usage description. 27 | 28 | # Android 29 | 30 | Specify your API key in the application manifest android/app/src/main/AndroidManifest.xml: 31 | 32 | ```xml 33 | 37 | ``` 38 | 39 | ## Sample Usage 40 | 41 | ```dart 42 | class HomePage extends StatelessWidget { 43 | @override 44 | Widget build(BuildContext context) { 45 | return Scaffold( 46 | body: PlatformMap( 47 | initialCameraPosition: CameraPosition( 48 | target: const LatLng(47.6, 8.8796), 49 | zoom: 16.0, 50 | ), 51 | markers: Set.of( 52 | [ 53 | Marker( 54 | markerId: MarkerId('marker_1'), 55 | position: LatLng(47.6, 8.8796), 56 | consumeTapEvents: true, 57 | infoWindow: InfoWindow( 58 | title: 'PlatformMarker', 59 | snippet: "Hi I'm a Platform Marker", 60 | ), 61 | onTap: () { 62 | print("Marker tapped"); 63 | }, 64 | ), 65 | ], 66 | ), 67 | myLocationEnabled: true, 68 | myLocationButtonEnabled: true, 69 | onTap: (location) => print('onTap: $location'), 70 | onCameraMove: (cameraUpdate) => print('onCameraMove: $cameraUpdate'), 71 | compassEnabled: true, 72 | onMapCreated: (controller) { 73 | Future.delayed(Duration(seconds: 2)).then( 74 | (_) { 75 | controller.animateCamera( 76 | CameraUpdate.newCameraPosition( 77 | const CameraPosition( 78 | bearing: 270.0, 79 | target: LatLng(51.5160895, -0.1294527), 80 | tilt: 30.0, 81 | zoom: 18, 82 | ), 83 | ), 84 | ); 85 | }, 86 | ); 87 | }, 88 | ), 89 | ); 90 | } 91 | } 92 | ``` 93 | 94 | Suggestions and PR's to make this plugin better are always welcome. Please notice that the features provided by this package depend on the apple_maps_flutter plugin, which will improve in the future. 95 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | - always_declare_return_types 6 | - avoid_annotating_with_dynamic 7 | - avoid_dynamic_calls 8 | - require_trailing_commas -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: c5a4b4029c0798f37c4a39b479d7cb75daa7b05c 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/README.md: -------------------------------------------------------------------------------- 1 | ## Sample Usage 2 | 3 | ```dart 4 | class HomePage extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return Scaffold( 8 | body: PlatformMap( 9 | initialCameraPosition: CameraPosition( 10 | target: const LatLng(47.6, 8.8796), 11 | zoom: 16.0, 12 | ), 13 | markers: Set.of( 14 | [ 15 | Marker( 16 | markerId: MarkerId('marker_1'), 17 | position: LatLng(47.6, 8.8796), 18 | consumeTapEvents: true, 19 | infoWindow: InfoWindow( 20 | title: 'PlatformMarker', 21 | snippet: "Hi I'm a Platform Marker", 22 | ), 23 | onTap: () { 24 | print("Marker tapped"); 25 | }, 26 | ), 27 | ], 28 | ), 29 | myLocationEnabled: true, 30 | myLocationButtonEnabled: true, 31 | onTap: (location) => print('onTap: $location'), 32 | onCameraMove: (cameraUpdate) => print('onCameraMove: $cameraUpdate'), 33 | compassEnabled: true, 34 | onMapCreated: (controller) { 35 | Future.delayed(Duration(seconds: 2)).then( 36 | (_) { 37 | controller.animateCamera( 38 | CameraUpdate.newCameraPosition( 39 | const CameraPosition( 40 | bearing: 270.0, 41 | target: LatLng(51.5160895, -0.1294527), 42 | tilt: 30.0, 43 | zoom: 18, 44 | ), 45 | ), 46 | ); 47 | }, 48 | ); 49 | }, 50 | ), 51 | ); 52 | } 53 | } 54 | ``` -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | - require_trailing_commas -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | android 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | 19 | 1602529678411 20 | 21 | 30 22 | 23 | org.eclipse.core.resources.regexFilterMatcher 24 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app 4 | Project app created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | 19 | 1602529678416 20 | 21 | 30 22 | 23 | org.eclipse.core.resources.regexFilterMatcher 24 | node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 34 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | defaultConfig { 36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | applicationId "com.example.flutter_platform_maps_example" 38 | minSdkVersion 20 39 | targetSdkVersion 34 40 | versionCode flutterVersionCode.toInteger() 41 | versionName flutterVersionName 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | namespace 'com.example.flutter_platform_maps_example' 52 | } 53 | 54 | flutter { 55 | source '../..' 56 | } 57 | 58 | dependencies { 59 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 60 | } 61 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 16 | 20 | 24 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/kotlin/com/example/flutter_platform_maps_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.flutter_platform_maps_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.8.21' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.4.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | tasks.register("clean", Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip 7 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - apple_maps_flutter (0.0.1): 3 | - Flutter 4 | - Flutter (1.0.0) 5 | 6 | DEPENDENCIES: 7 | - apple_maps_flutter (from `.symlinks/plugins/apple_maps_flutter/ios`) 8 | - Flutter (from `Flutter`) 9 | 10 | EXTERNAL SOURCES: 11 | apple_maps_flutter: 12 | :path: ".symlinks/plugins/apple_maps_flutter/ios" 13 | Flutter: 14 | :path: Flutter 15 | 16 | SPEC CHECKSUMS: 17 | apple_maps_flutter: c59725efea39e13e703cde52a1d2b14866ad68a8 18 | Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 19 | 20 | PODFILE CHECKSUM: 4e8f8b2be68aeea4c0d5beb6ff1e79fface1d048 21 | 22 | COCOAPODS: 1.15.0 23 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/platform_maps_flutter/070934913ac77f8e583ae2110affa39d810c493a/packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_platform_maps_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:platform_maps_flutter/platform_maps_flutter.dart'; 3 | 4 | void main() => runApp(const MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | const MyApp({Key? key}) : super(key: key); 8 | 9 | // This widget is the root of your application. 10 | @override 11 | Widget build(BuildContext context) { 12 | return const MaterialApp( 13 | home: MyHomePage(), 14 | ); 15 | } 16 | } 17 | 18 | class MyHomePage extends StatefulWidget { 19 | const MyHomePage({Key? key}) : super(key: key); 20 | 21 | @override 22 | State createState() => _MyHomePageState(); 23 | } 24 | 25 | class _MyHomePageState extends State { 26 | @override 27 | Widget build(BuildContext context) { 28 | return Scaffold( 29 | body: PlatformMap( 30 | initialCameraPosition: const CameraPosition( 31 | target: LatLng(47.6, 8.8796), 32 | zoom: 16.0, 33 | ), 34 | markers: { 35 | Marker( 36 | markerId: const MarkerId('marker_1'), 37 | position: const LatLng(47.6, 8.8796), 38 | consumeTapEvents: true, 39 | infoWindow: const InfoWindow( 40 | title: 'PlatformMarker', 41 | snippet: "Hi I'm a Platform Marker", 42 | ), 43 | onTap: () { 44 | debugPrint("Marker tapped"); 45 | }, 46 | ), 47 | }, 48 | mapType: MapType.satellite, 49 | onTap: (location) => debugPrint('onTap: $location'), 50 | onCameraMove: (cameraUpdate) => 51 | debugPrint('onCameraMove: $cameraUpdate'), 52 | compassEnabled: true, 53 | onMapCreated: (controller) { 54 | Future.delayed(const Duration(seconds: 2)).then( 55 | (_) { 56 | controller.animateCamera( 57 | CameraUpdate.newCameraPosition( 58 | const CameraPosition( 59 | bearing: 270.0, 60 | target: LatLng(51.5160895, -0.1294527), 61 | tilt: 30.0, 62 | zoom: 18, 63 | ), 64 | ), 65 | ); 66 | controller 67 | .getVisibleRegion() 68 | .then((bounds) => debugPrint("bounds: ${bounds.toString()}")); 69 | }, 70 | ); 71 | }, 72 | ), 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_platform_maps_example 2 | publish_to: 'none' 3 | version: 1.0.0+1 4 | 5 | environment: 6 | sdk: ">=2.12.0 <3.0.0" 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | 12 | platform_maps_flutter: 13 | path: ../ 14 | 15 | cupertino_icons: ^1.0.2 16 | 17 | dev_dependencies: 18 | flutter_lints: ^3.0.1 19 | flutter_test: 20 | sdk: flutter 21 | 22 | flutter: 23 | uses-material-design: true 24 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/lib/platform_maps_flutter.dart: -------------------------------------------------------------------------------- 1 | library platform_maps_flutter; 2 | 3 | export 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart' 4 | show 5 | ArgumentCallback, 6 | BitmapDescriptor, 7 | CameraPosition, 8 | CameraPositionCallback, 9 | CameraUpdate, 10 | Circle, 11 | InfoWindow, 12 | LatLng, 13 | LatLngBounds, 14 | MapType, 15 | Marker, 16 | MarkerId, 17 | MinMaxZoomPreference, 18 | PlatformMap, 19 | PlatformMapController, 20 | Polygon, 21 | Polyline; 22 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: platform_maps_flutter 2 | description: A Flutter package that combines google_maps and apple_maps to provide a crossplatform native map implementation. 3 | version: 2.0.0-beta 4 | homepage: https://github.com/albert-heijn-technology 5 | repository: https://github.com/albert-heijn-technology/platform_maps_flutter/tree/master/packages/platform_maps_flutter 6 | issue_tracker: https://github.com/albert-heijn-technology/platform_maps_flutter/issues 7 | 8 | environment: 9 | flutter: '>=2.11.0' 10 | sdk: '>=2.17.0 <4.0.0' 11 | 12 | flutter: 13 | plugin: 14 | platforms: 15 | android: 16 | default_package: platform_maps_flutter_google_android 17 | ios: 18 | default_package: platform_maps_flutter_apple 19 | 20 | dependencies: 21 | flutter: 22 | sdk: flutter 23 | 24 | platform_maps_flutter_apple: ^1.0.0-beta 25 | platform_maps_flutter_google_android: ^1.0.0-beta 26 | platform_maps_flutter_platform_interface: ^1.0.0-beta 27 | 28 | dev_dependencies: 29 | flutter_lints: ^3.0.1 30 | flutter_test: 31 | sdk: flutter 32 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter/test/platform_maps_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 4 | 5 | void main() { 6 | testWidgets('Load platform widget', (tester) async { 7 | PlatformMapsPlatform.instance = FakePlatform(); 8 | 9 | await tester.pumpWidget( 10 | MaterialApp( 11 | home: Scaffold( 12 | body: PlatformMap( 13 | initialCameraPosition: const CameraPosition( 14 | target: LatLng(4.4, 5.5), 15 | ), 16 | ), 17 | ), 18 | ), 19 | ); 20 | 21 | expect(find.text('4.4,5.5'), findsOneWidget); 22 | }); 23 | } 24 | 25 | class FakePlatform extends PlatformMapsPlatform { 26 | @override 27 | PlatformMapsPlatformWidget createPlatformMapsPlatformWidget( 28 | PlatformMapsPlatformWidgetCreationParams params, 29 | ) { 30 | return FakeWidget(params); 31 | } 32 | } 33 | 34 | class FakeWidget extends PlatformMapsPlatformWidget { 35 | FakeWidget(super.params) : super.implementation(); 36 | 37 | @override 38 | Widget build(BuildContext context) { 39 | final target = params.initialCameraPosition.target; 40 | return Center(child: Text('${target.latitude},${target.longitude}')); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | build/ 30 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "ef1af02aead6fe2414f3aafa5a61087b610e1332" 8 | channel: "stable" 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0-beta 2 | 3 | * Initial version, based on platform_maps_flutter 1.0.2 4 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2024, Albert Heijn Technology 4 | Copyright (c) 2019, Luis Thein 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/README.md: -------------------------------------------------------------------------------- 1 | # platform_maps_flutter_apple 2 | 3 | This is the Apple (iOS) implementation of the `platform_maps_flutter` plugin. 4 | If you add `platform_maps_flutter` to your pubspec.yaml this will automatically be used. -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | - require_trailing_commas 6 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/lib/platform_maps_flutter_apple.dart: -------------------------------------------------------------------------------- 1 | library platform_maps_flutter_apple; 2 | 3 | import 'package:platform_maps_flutter_apple/src/apple_maps_bitmap_descriptor.dart'; 4 | import 'package:platform_maps_flutter_apple/src/apple_maps_camera_update.dart'; 5 | import 'package:platform_maps_flutter_apple/src/apple_maps_widget.dart'; 6 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 7 | 8 | class PlatformMapsApple extends PlatformMapsPlatform { 9 | static void registerWith() { 10 | PlatformMapsPlatform.instance = PlatformMapsApple(); 11 | } 12 | 13 | /// Create a new [PlatformPlatformMapsWidget]. 14 | /// 15 | /// This function should only be called by the app-facing package. 16 | /// Look at using [PlatformMap] in `platform_maps_flutter` instead. 17 | @override 18 | PlatformMapsPlatformWidget createPlatformMapsPlatformWidget( 19 | PlatformMapsPlatformWidgetCreationParams params, 20 | ) { 21 | return AppleMapsWidget(params); 22 | } 23 | 24 | /// Create a new [PlatformBitmapDescriptor]. 25 | /// This function should only be called by the app-facing package. 26 | @override 27 | PlatformBitmapDescriptor createBitmapDescriptor() { 28 | return AppleMapsPlatformBitmapDescriptor(); 29 | } 30 | 31 | @override 32 | PlatformCameraUpdate createPlatformCameraUpdate() { 33 | return AppleMapsPlatformCameraUpdate(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/lib/src/apple_maps_bitmap_descriptor.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 5 | import 'package:apple_maps_flutter/apple_maps_flutter.dart' as apple_maps; 6 | 7 | class AppleMapsPlatformBitmapDescriptor extends PlatformBitmapDescriptor { 8 | AppleMapsPlatformBitmapDescriptor() : super.implementation(); 9 | @override 10 | Future fromAssetImage( 11 | ImageConfiguration configuration, 12 | String assetName, { 13 | AssetBundle? bundle, 14 | String? package, 15 | }) async { 16 | final descriptor = await apple_maps.BitmapDescriptor.fromAssetImage( 17 | configuration, 18 | assetName, 19 | bundle: bundle, 20 | package: package, 21 | ); 22 | return AppleMapsBitmapDescriptor(descriptor); 23 | } 24 | 25 | @override 26 | AppleMapsBitmapDescriptor fromBytes(Uint8List byteData) { 27 | return AppleMapsBitmapDescriptor( 28 | apple_maps.BitmapDescriptor.fromBytes(byteData), 29 | ); 30 | } 31 | } 32 | 33 | class AppleMapsBitmapDescriptor extends BitmapDescriptor { 34 | AppleMapsBitmapDescriptor(this.descriptor); 35 | apple_maps.BitmapDescriptor descriptor; 36 | } 37 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/lib/src/apple_maps_camera_update.dart: -------------------------------------------------------------------------------- 1 | import 'package:apple_maps_flutter/apple_maps_flutter.dart' as apple_maps; 2 | import 'package:platform_maps_flutter_apple/src/mapper_extensions.dart'; 3 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 4 | 5 | class AppleMapsPlatformCameraUpdate extends PlatformCameraUpdate { 6 | AppleMapsPlatformCameraUpdate() : super.implementation(); 7 | 8 | @override 9 | CameraUpdate newCameraPosition(CameraPosition cameraPosition) { 10 | return AppleMapsCameraUpdate._( 11 | apple_maps.CameraUpdate.newCameraPosition( 12 | cameraPosition.appleMapsCameraPosition, 13 | ), 14 | ); 15 | } 16 | 17 | @override 18 | CameraUpdate newLatLng(LatLng latLng) { 19 | return AppleMapsCameraUpdate._( 20 | apple_maps.CameraUpdate.newLatLng( 21 | latLng.appleMapsLatLng, 22 | ), 23 | ); 24 | } 25 | 26 | @override 27 | CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) { 28 | return AppleMapsCameraUpdate._( 29 | apple_maps.CameraUpdate.newLatLngBounds( 30 | bounds.appleMapsLatLngBounds, 31 | padding, 32 | ), 33 | ); 34 | } 35 | 36 | @override 37 | CameraUpdate newLatLngZoom(LatLng latLng, double zoom) { 38 | return AppleMapsCameraUpdate._( 39 | apple_maps.CameraUpdate.newLatLngZoom( 40 | latLng.appleMapsLatLng, 41 | zoom, 42 | ), 43 | ); 44 | } 45 | 46 | @override 47 | CameraUpdate zoomBy(double amount) { 48 | return AppleMapsCameraUpdate._( 49 | apple_maps.CameraUpdate.zoomBy(amount), 50 | ); 51 | } 52 | 53 | @override 54 | CameraUpdate zoomIn() { 55 | return AppleMapsCameraUpdate._( 56 | apple_maps.CameraUpdate.zoomIn(), 57 | ); 58 | } 59 | 60 | @override 61 | CameraUpdate zoomOut() { 62 | return AppleMapsCameraUpdate._( 63 | apple_maps.CameraUpdate.zoomOut(), 64 | ); 65 | } 66 | 67 | @override 68 | CameraUpdate zoomTo(double zoom) { 69 | return AppleMapsCameraUpdate._( 70 | apple_maps.CameraUpdate.zoomTo(zoom), 71 | ); 72 | } 73 | } 74 | 75 | class AppleMapsCameraUpdate extends CameraUpdate { 76 | const AppleMapsCameraUpdate._(this.appleMapsCameraUpdate); 77 | final apple_maps.CameraUpdate appleMapsCameraUpdate; 78 | } 79 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/lib/src/apple_maps_platform_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:apple_maps_flutter/apple_maps_flutter.dart' as apple_maps; 4 | import 'package:platform_maps_flutter_apple/src/apple_maps_camera_update.dart'; 5 | import 'package:platform_maps_flutter_apple/src/mapper_extensions.dart'; 6 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 7 | 8 | class AppleMapsPlatformController extends PlatformMapsPlatformController { 9 | AppleMapsPlatformController(this._appleMapController); 10 | final apple_maps.AppleMapController _appleMapController; 11 | 12 | @override 13 | Future animateCamera(CameraUpdate cameraUpdate) { 14 | if (cameraUpdate is AppleMapsCameraUpdate) { 15 | return _appleMapController 16 | .animateCamera(cameraUpdate.appleMapsCameraUpdate); 17 | } 18 | throw UnsupportedError( 19 | 'AppleMapsPlatformController: animateCamera - cameraUpdate is not a AppleMapsCameraUpdate\n${cameraUpdate.toString()}', 20 | ); 21 | } 22 | 23 | @override 24 | Future getVisibleRegion() async { 25 | final visibleRegion = await _appleMapController.getVisibleRegion(); 26 | return visibleRegion.platformLatLngBounds; 27 | } 28 | 29 | @override 30 | Future hideMarkerInfoWindow(MarkerId markerId) { 31 | return _appleMapController 32 | .hideMarkerInfoWindow(markerId.appleMapsAnnotationId); 33 | } 34 | 35 | @override 36 | Future isMarkerInfoWindowShown(MarkerId markerId) async { 37 | return (await _appleMapController 38 | .isMarkerInfoWindowShown(markerId.appleMapsAnnotationId)) ?? 39 | false; 40 | } 41 | 42 | @override 43 | Future moveCamera(CameraUpdate cameraUpdate) { 44 | if (cameraUpdate is AppleMapsCameraUpdate) { 45 | return _appleMapController.moveCamera(cameraUpdate.appleMapsCameraUpdate); 46 | } 47 | throw UnsupportedError( 48 | 'AppleMapsPlatformController: moveCamera - cameraUpdate is not a AppleMapsCameraUpdate\n${cameraUpdate.toString()}', 49 | ); 50 | } 51 | 52 | @override 53 | Future showMarkerInfoWindow(MarkerId markerId) { 54 | return _appleMapController 55 | .showMarkerInfoWindow(markerId.appleMapsAnnotationId); 56 | } 57 | 58 | @override 59 | Future takeSnapshot() { 60 | return _appleMapController.takeSnapshot(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/lib/src/apple_maps_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/gestures.dart'; 3 | import 'package:flutter/widgets.dart'; 4 | import 'package:platform_maps_flutter_apple/src/mapper_extensions.dart'; 5 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 6 | import 'package:apple_maps_flutter/apple_maps_flutter.dart' as apple_maps; 7 | 8 | class AppleMapsWidget extends PlatformMapsPlatformWidget { 9 | AppleMapsWidget(PlatformMapsPlatformWidgetCreationParams params) 10 | : super.implementation(params); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return _PlatformMap(params: params); 15 | } 16 | } 17 | 18 | class _PlatformMap extends StatefulWidget { 19 | const _PlatformMap({ 20 | required this.params, 21 | }); 22 | 23 | final PlatformMapsPlatformWidgetCreationParams params; 24 | 25 | /// Callback method for when the map is ready to be used. 26 | /// 27 | /// Used to receive a [AppleMapController] for this [AppleMap]. 28 | MapCreatedCallback? get onMapCreated => params.onMapCreated; 29 | 30 | /// The initial position of the map's camera. 31 | CameraPosition get initialCameraPosition => params.initialCameraPosition; 32 | 33 | /// True if the map should show a compass when rotated. 34 | bool get compassEnabled => params.compassEnabled; 35 | 36 | /// Type of map tiles to be rendered. 37 | MapType get mapType => params.mapType; 38 | 39 | /// Preferred bounds for the camera zoom level. 40 | /// 41 | /// Actual bounds depend on map data and device. 42 | MinMaxZoomPreference get minMaxZoomPreference => params.minMaxZoomPreference; 43 | 44 | /// True if the map view should respond to rotate gestures. 45 | bool get rotateGesturesEnabled => params.rotateGesturesEnabled; 46 | 47 | /// True if the map view should respond to scroll gestures. 48 | bool get scrollGesturesEnabled => params.scrollGesturesEnabled; 49 | 50 | /// True if the map view should show zoom controls. This includes two buttons 51 | /// to zoom in and zoom out. The default value is to show zoom controls. 52 | /// 53 | /// This is only supported on Android. And this field is silently ignored on iOS. 54 | bool get zoomControlsEnabled => params.zoomControlsEnabled; 55 | 56 | /// True if the map view should respond to zoom gestures. 57 | bool get zoomGesturesEnabled => params.zoomGesturesEnabled; 58 | 59 | /// True if the map view should respond to tilt gestures. 60 | bool get tiltGesturesEnabled => params.tiltGesturesEnabled; 61 | 62 | /// Padding to be set on map. 63 | EdgeInsets get padding => params.padding; 64 | 65 | /// Markers to be placed on the map. 66 | Set get markers => params.markers; 67 | 68 | /// Polygons to be placed on the map. 69 | Set get polygons => params.polygons; 70 | 71 | /// Polylines to be placed on the map. 72 | Set get polylines => params.polylines; 73 | 74 | /// Circles to be placed on the map. 75 | Set get circles => params.circles; 76 | 77 | /// Called when the camera starts moving. 78 | /// 79 | /// This can be initiated by the following: 80 | /// 1. Non-gesture animation initiated in response to user actions. 81 | /// For example: zoom buttons, my location button, or marker clicks. 82 | /// 2. Programmatically initiated animation. 83 | /// 3. Camera motion initiated in response to user gestures on the map. 84 | /// For example: pan, tilt, pinch to zoom, or rotate. 85 | VoidCallback? get onCameraMoveStarted => params.onCameraMoveStarted; 86 | 87 | /// Called repeatedly as the camera continues to move after an 88 | /// onCameraMoveStarted call. 89 | /// 90 | /// This may be called as often as once every frame and should 91 | /// not perform expensive operations. 92 | CameraPositionCallback? get onCameraMove => params.onCameraMove; 93 | 94 | /// Called when camera movement has ended, there are no pending 95 | /// animations and the user has stopped interacting with the map. 96 | VoidCallback? get onCameraIdle => params.onCameraIdle; 97 | 98 | /// Called every time a [PlatformMap] is tapped. 99 | ArgumentCallback? get onTap => params.onTap; 100 | 101 | /// Called every time a [PlatformMap] is long pressed. 102 | ArgumentCallback? get onLongPress => params.onLongPress; 103 | 104 | /// True if a "My Location" layer should be shown on the map. 105 | /// 106 | /// This layer includes a location indicator at the current device location, 107 | /// as well as a My Location button. 108 | /// * The indicator is a small blue dot if the device is stationary, or a 109 | /// chevron if the device is moving. 110 | /// * The My Location button animates to focus on the user's current location 111 | /// if the user's location is currently known. 112 | /// 113 | /// Enabling this feature requires adding location permissions to both native 114 | /// platforms of your app. 115 | /// * On Android add either 116 | /// `` 117 | /// or `` 118 | /// to your `AndroidManifest.xml` file. `ACCESS_COARSE_LOCATION` returns a 119 | /// location with an accuracy approximately equivalent to a city block, while 120 | /// `ACCESS_FINE_LOCATION` returns as precise a location as possible, although 121 | /// it consumes more battery power. You will also need to request these 122 | /// permissions during run-time. If they are not granted, the My Location 123 | /// feature will fail silently. 124 | /// * On iOS add a `NSLocationWhenInUseUsageDescription` key to your 125 | /// `Info.plist` file. This will automatically prompt the user for permissions 126 | /// when the map tries to turn on the My Location layer. 127 | bool get myLocationEnabled => params.myLocationEnabled; 128 | 129 | /// Enables or disables the my-location button. 130 | /// 131 | /// The my-location button causes the camera to move such that the user's 132 | /// location is in the center of the map. If the button is enabled, it is 133 | /// only shown when the my-location layer is enabled. 134 | /// 135 | /// By default, the my-location button is enabled (and hence shown when the 136 | /// my-location layer is enabled). 137 | /// 138 | /// See also: 139 | /// * [myLocationEnabled] parameter. 140 | bool get myLocationButtonEnabled => params.myLocationButtonEnabled; 141 | 142 | /// Enables or disables the traffic layer of the map 143 | bool get trafficEnabled => params.trafficEnabled; 144 | 145 | /// Which gestures should be consumed by the map. 146 | /// 147 | /// It is possible for other gesture recognizers to be competing with the map on pointer 148 | /// events, e.g if the map is inside a [ListView] the [ListView] will want to handle 149 | /// vertical drags. The map will claim gestures that are recognized by any of the 150 | /// recognizers on this list. 151 | /// 152 | /// When this set is empty, the map will only handle pointer events for gestures that 153 | /// were not claimed by any other gesture recognizer. 154 | Set> get gestureRecognizers => 155 | params.gestureRecognizers; 156 | @override 157 | _PlatformMapState createState() => _PlatformMapState(); 158 | } 159 | 160 | class _PlatformMapState extends State<_PlatformMap> { 161 | @override 162 | Widget build(BuildContext context) { 163 | return apple_maps.AppleMap( 164 | initialCameraPosition: 165 | widget.initialCameraPosition.appleMapsCameraPosition, 166 | compassEnabled: widget.compassEnabled, 167 | mapType: _getMapType(), 168 | padding: widget.padding, 169 | annotations: widget.markers.appleMapsAnnotationSet, 170 | polylines: widget.polylines.appleMapsPolylineSet, 171 | polygons: widget.polygons.appleMapsPolygonSet, 172 | circles: widget.circles.appleMapsCircleSet, 173 | gestureRecognizers: widget.gestureRecognizers, 174 | onCameraIdle: widget.onCameraIdle, 175 | myLocationButtonEnabled: widget.myLocationButtonEnabled, 176 | myLocationEnabled: widget.myLocationEnabled, 177 | onCameraMoveStarted: widget.onCameraMoveStarted, 178 | pitchGesturesEnabled: widget.tiltGesturesEnabled, 179 | rotateGesturesEnabled: widget.rotateGesturesEnabled, 180 | zoomGesturesEnabled: widget.zoomGesturesEnabled, 181 | scrollGesturesEnabled: widget.scrollGesturesEnabled, 182 | onMapCreated: _onMapCreated, 183 | onCameraMove: _onCameraMove, 184 | onTap: _onTap, 185 | onLongPress: _onLongPress, 186 | trafficEnabled: widget.trafficEnabled, 187 | minMaxZoomPreference: widget.minMaxZoomPreference.appleMapsZoomPreference, 188 | ); 189 | } 190 | 191 | void _onMapCreated(apple_maps.AppleMapController controller) { 192 | widget.onMapCreated?.call(controller.platformMapController); 193 | } 194 | 195 | void _onCameraMove(apple_maps.CameraPosition cameraPosition) { 196 | widget.onCameraMove?.call(cameraPosition.platformCameraPosition); 197 | } 198 | 199 | void _onTap(apple_maps.LatLng position) { 200 | widget.onTap?.call(position.platformLatLng); 201 | } 202 | 203 | void _onLongPress(apple_maps.LatLng position) { 204 | widget.onLongPress?.call(position.platformLatLng); 205 | } 206 | 207 | apple_maps.MapType _getMapType() { 208 | switch (widget.mapType) { 209 | case MapType.normal: 210 | return apple_maps.MapType.standard; 211 | case MapType.satellite: 212 | return apple_maps.MapType.satellite; 213 | case MapType.hybrid: 214 | return apple_maps.MapType.hybrid; 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/lib/src/mapper_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:apple_maps_flutter/apple_maps_flutter.dart' as apple_maps; 4 | import 'package:platform_maps_flutter_apple/src/apple_maps_bitmap_descriptor.dart'; 5 | import 'package:platform_maps_flutter_apple/src/apple_maps_platform_controller.dart'; 6 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 7 | 8 | extension AppleMapsLatLngMapper on apple_maps.LatLng { 9 | LatLng get platformLatLng { 10 | return LatLng(latitude, longitude); 11 | } 12 | } 13 | 14 | extension LatLngMapper on LatLng { 15 | apple_maps.LatLng get appleMapsLatLng { 16 | return apple_maps.LatLng(latitude, longitude); 17 | } 18 | } 19 | 20 | extension on List { 21 | List get appleLatLngList { 22 | return map((latLng) => latLng.appleMapsLatLng).toList(); 23 | } 24 | } 25 | 26 | extension LatLngBoundsMapper on LatLngBounds { 27 | apple_maps.LatLngBounds get appleMapsLatLngBounds { 28 | return apple_maps.LatLngBounds( 29 | southwest: southwest.appleMapsLatLng, 30 | northeast: northeast.appleMapsLatLng, 31 | ); 32 | } 33 | } 34 | 35 | extension AppleMapsLatLngBoundsMapper on apple_maps.LatLngBounds { 36 | LatLngBounds get platformLatLngBounds { 37 | return LatLngBounds( 38 | southwest: southwest.platformLatLng, 39 | northeast: northeast.platformLatLng, 40 | ); 41 | } 42 | } 43 | 44 | extension MarkersMapper on Set { 45 | Set get appleMapsAnnotationSet { 46 | return map((marker) => marker.appleMapsAnnotation).toSet(); 47 | } 48 | } 49 | 50 | extension on Marker { 51 | apple_maps.Annotation get appleMapsAnnotation => apple_maps.Annotation( 52 | annotationId: markerId.appleMapsAnnotationId, 53 | alpha: alpha, 54 | anchor: anchor, 55 | draggable: draggable, 56 | infoWindow: infoWindow.appleMapsInfoWindow, 57 | onTap: onTap, 58 | icon: (icon as AppleMapsBitmapDescriptor?)?.descriptor ?? 59 | apple_maps.BitmapDescriptor.defaultAnnotation, 60 | visible: visible, 61 | onDragEnd: onDragEnd != null 62 | ? (apple_maps.LatLng latLng) => _onDragEnd(latLng, onDragEnd) 63 | : null, 64 | position: position.appleMapsLatLng, 65 | ); 66 | 67 | static _onDragEnd(apple_maps.LatLng latLng, Function? onDragEnd) { 68 | onDragEnd?.call(latLng.platformLatLng); 69 | } 70 | } 71 | 72 | extension MarkerIdMapper on MarkerId { 73 | apple_maps.AnnotationId get appleMapsAnnotationId { 74 | return apple_maps.AnnotationId(value); 75 | } 76 | } 77 | 78 | extension on InfoWindow { 79 | apple_maps.InfoWindow get appleMapsInfoWindow => apple_maps.InfoWindow( 80 | anchor: anchor ?? const Offset(0, 0), 81 | onTap: onTap, 82 | snippet: snippet, 83 | title: title, 84 | ); 85 | } 86 | 87 | extension CameraMapper on CameraPosition { 88 | apple_maps.CameraPosition get appleMapsCameraPosition { 89 | return apple_maps.CameraPosition( 90 | target: target.appleMapsLatLng, 91 | heading: bearing, 92 | pitch: tilt, 93 | zoom: zoom, 94 | ); 95 | } 96 | } 97 | 98 | extension AppleMapsCameraMapper on apple_maps.CameraPosition { 99 | CameraPosition get platformCameraPosition { 100 | return CameraPosition( 101 | target: target.platformLatLng, 102 | bearing: heading, 103 | tilt: pitch, 104 | zoom: zoom, 105 | ); 106 | } 107 | } 108 | 109 | extension PolylinesMapper on Set { 110 | Set get appleMapsPolylineSet { 111 | return map((polyline) => polyline.appleMapsPolyline).toSet(); 112 | } 113 | } 114 | 115 | extension on Polyline { 116 | apple_maps.Polyline get appleMapsPolyline { 117 | return apple_maps.Polyline( 118 | polylineId: polylineId.appleMapsPolylineId, 119 | color: color, 120 | consumeTapEvents: consumeTapEvents, 121 | polylineCap: polylineCap.applePolylineCap, 122 | jointType: jointType.appleMapsJointType, 123 | onTap: onTap, 124 | patterns: patterns.appleMapsPatternItemList, 125 | points: points.appleLatLngList, 126 | visible: visible, 127 | width: width, 128 | ); 129 | } 130 | } 131 | 132 | extension on PolylineId { 133 | apple_maps.PolylineId get appleMapsPolylineId { 134 | return apple_maps.PolylineId(value); 135 | } 136 | } 137 | 138 | extension on Cap { 139 | static const Map appleMapsCaps = { 140 | Cap.buttCap: apple_maps.Cap.buttCap, 141 | Cap.roundCap: apple_maps.Cap.roundCap, 142 | Cap.squareCap: apple_maps.Cap.squareCap, 143 | }; 144 | 145 | apple_maps.Cap get applePolylineCap { 146 | return appleMapsCaps[this]!; 147 | } 148 | } 149 | 150 | extension on JointType { 151 | static const List appleMapsJointTypes = [ 152 | apple_maps.JointType.mitered, 153 | apple_maps.JointType.bevel, 154 | apple_maps.JointType.round, 155 | ]; 156 | 157 | apple_maps.JointType get appleMapsJointType { 158 | return appleMapsJointTypes[value]; 159 | } 160 | } 161 | 162 | extension on List { 163 | List get appleMapsPatternItemList { 164 | return map((patternItem) => patternItem.appleMapsPatternItem).toList(); 165 | } 166 | } 167 | 168 | extension on PatternItem { 169 | apple_maps.PatternItem get appleMapsPatternItem { 170 | return switch (this) { 171 | DotPatternItem() => apple_maps.PatternItem.dot, 172 | DashPatternItem dash => apple_maps.PatternItem.dash(dash.length), 173 | GapPatternItem gap => apple_maps.PatternItem.gap(gap.length), 174 | }; 175 | } 176 | } 177 | 178 | extension PolygonMapper on Set { 179 | Set get appleMapsPolygonSet { 180 | return map((polygon) => polygon.appleMapsPolygon).toSet(); 181 | } 182 | } 183 | 184 | extension on Polygon { 185 | apple_maps.Polygon get appleMapsPolygon { 186 | return apple_maps.Polygon( 187 | polygonId: apple_maps.PolygonId(polygonId.value), 188 | consumeTapEvents: consumeTapEvents, 189 | fillColor: fillColor, 190 | onTap: onTap, 191 | points: points.appleLatLngList, 192 | strokeColor: strokeColor, 193 | strokeWidth: strokeWidth, 194 | visible: visible, 195 | ); 196 | } 197 | } 198 | 199 | extension CircleMapper on Set { 200 | Set get appleMapsCircleSet { 201 | return map((circle) => circle.appleMapsCircle).toSet(); 202 | } 203 | } 204 | 205 | extension on Circle { 206 | apple_maps.Circle get appleMapsCircle { 207 | return apple_maps.Circle( 208 | circleId: apple_maps.CircleId(circleId.value), 209 | consumeTapEvents: consumeTapEvents, 210 | fillColor: fillColor, 211 | onTap: onTap, 212 | center: center.appleMapsLatLng, 213 | radius: radius, 214 | strokeColor: strokeColor, 215 | strokeWidth: strokeWidth, 216 | visible: visible, 217 | ); 218 | } 219 | } 220 | 221 | extension ZoomMapper on MinMaxZoomPreference { 222 | apple_maps.MinMaxZoomPreference get appleMapsZoomPreference { 223 | return apple_maps.MinMaxZoomPreference(minZoom, maxZoom); 224 | } 225 | } 226 | 227 | extension AppleMapsControllerMappers on apple_maps.AppleMapController { 228 | PlatformMapController get platformMapController { 229 | return PlatformMapController(AppleMapsPlatformController(this)); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: platform_maps_flutter_apple 2 | description: Apple Maps implementation for the platform_maps_flutter plugin. 3 | version: 1.0.0-beta 4 | homepage: https://github.com/albert-heijn-technology 5 | repository: https://github.com/albert-heijn-technology/platform_maps_flutter/tree/master/packages/platform_maps_flutter_apple 6 | issue_tracker: https://github.com/albert-heijn-technology/platform_maps_flutter/issues 7 | 8 | environment: 9 | sdk: '>=3.2.4 <4.0.0' 10 | flutter: ">=1.17.0" 11 | 12 | flutter: 13 | plugin: 14 | implements: platform_maps_flutter 15 | platforms: 16 | ios: 17 | dartPluginClass: PlatformMapsApple 18 | fileName: platform_maps_flutter_apple.dart 19 | 20 | dependencies: 21 | flutter: 22 | sdk: flutter 23 | apple_maps_flutter: ^1.3.0 24 | platform_maps_flutter_platform_interface: ^1.0.0-beta 25 | 26 | dev_dependencies: 27 | flutter_test: 28 | sdk: flutter 29 | flutter_lints: ^2.0.0 30 | 31 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_apple/test/platform_maps_flutter_apple_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter_test/flutter_test.dart'; 4 | import 'package:platform_maps_flutter_apple/platform_maps_flutter_apple.dart'; 5 | import 'package:platform_maps_flutter_apple/src/apple_maps_bitmap_descriptor.dart'; 6 | import 'package:platform_maps_flutter_apple/src/apple_maps_camera_update.dart'; 7 | import 'package:platform_maps_flutter_apple/src/apple_maps_widget.dart'; 8 | 9 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 10 | 11 | void main() { 12 | test('Verify widget generation', () { 13 | PlatformMapsApple.registerWith(); 14 | 15 | final widget = PlatformMapsPlatformWidget( 16 | const PlatformMapsPlatformWidgetCreationParams( 17 | initialCameraPosition: CameraPosition(target: LatLng(0, 0)), 18 | ), 19 | ); 20 | expect(widget, isA()); 21 | }); 22 | 23 | test('Verify bitmap descriptor generation', () { 24 | PlatformMapsApple.registerWith(); 25 | 26 | final platformBitmapDescriptor = PlatformBitmapDescriptor(); 27 | expect(platformBitmapDescriptor, isA()); 28 | 29 | final bitmapDescriptor = platformBitmapDescriptor.fromBytes(Uint8List(0)); 30 | expect(bitmapDescriptor, isA()); 31 | }); 32 | 33 | test('Verify camera update generation', () { 34 | PlatformMapsApple.registerWith(); 35 | 36 | final platformCameraUpdate = PlatformCameraUpdate(); 37 | expect(platformCameraUpdate, isA()); 38 | 39 | final cameraUpdate = platformCameraUpdate.zoomIn(); 40 | expect(cameraUpdate, isA()); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | build/ 30 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "ef1af02aead6fe2414f3aafa5a61087b610e1332" 8 | channel: "stable" 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0-beta 2 | 3 | * Initial version, based on platform_maps_flutter 1.0.2 4 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2024, Albert Heijn Technology 4 | Copyright (c) 2019, Luis Thein 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/README.md: -------------------------------------------------------------------------------- 1 | # platform_maps_flutter_google_android 2 | 3 | This is the Google Maps for Android implementation of the `platform_maps_flutter` plugin. 4 | If you add `platform_maps_flutter` to your pubspec.yaml this will automatically be used. 5 | 6 | It's Android only to prevent iOS dependencies for Google Maps being added to your project. -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | - require_trailing_commas 6 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/lib/platform_maps_flutter_google_android.dart: -------------------------------------------------------------------------------- 1 | library platform_maps_flutter_google_android; 2 | 3 | import 'package:platform_maps_flutter_google_android/src/google_maps_bitmap_descriptor.dart'; 4 | import 'package:platform_maps_flutter_google_android/src/google_maps_camera_update.dart'; 5 | import 'package:platform_maps_flutter_google_android/src/google_maps_widget.dart'; 6 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 7 | 8 | class PlatformMapsGoogleAndroid extends PlatformMapsPlatform { 9 | static void registerWith() { 10 | PlatformMapsPlatform.instance = PlatformMapsGoogleAndroid(); 11 | } 12 | 13 | /// Create a new [PlatformPlatformMapsWidget]. 14 | /// 15 | /// This function should only be called by the app-facing package. 16 | /// Look at using [PlatformMap] in `platform_maps_flutter` instead. 17 | @override 18 | PlatformMapsPlatformWidget createPlatformMapsPlatformWidget( 19 | PlatformMapsPlatformWidgetCreationParams params, 20 | ) { 21 | return GoogleMapsWidget(params); 22 | } 23 | 24 | /// Create a new [PlatformBitmapDescriptor]. 25 | /// This function should only be called by the app-facing package. 26 | @override 27 | GoogleMapsPlatformBitmapDescriptor createBitmapDescriptor() { 28 | return GoogleMapsPlatformBitmapDescriptor(); 29 | } 30 | 31 | @override 32 | PlatformCameraUpdate createPlatformCameraUpdate() { 33 | return GoogleMapsPlatformCameraUpdate(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/lib/src/google_map_original.dart: -------------------------------------------------------------------------------- 1 | /// These files are literal copies of [google_maps_flutter](https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter/lib/src) 2 | /// We cannot depend on google_maps_flutter directly as it will include google_maps_ios and its native artifacts. 3 | /// 4 | /// Can be updated if this issue is resolved: https://github.com/flutter/flutter/issues/81650 5 | /// Related discussion: https://github.com/flutter/flutter/issues/148210 6 | export 'google_map_original/google_map.dart'; 7 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/lib/src/google_map_original/controller.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Flutter Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | // ignore_for_file: library_private_types_in_public_api 6 | 7 | part of 'google_map.dart'; 8 | 9 | /// Controller for a single GoogleMap instance running on the host platform. 10 | class GoogleMapController { 11 | GoogleMapController._( 12 | this._googleMapState, { 13 | required this.mapId, 14 | }) { 15 | _connectStreams(mapId); 16 | } 17 | 18 | /// The mapId for this controller 19 | final int mapId; 20 | 21 | /// Initialize control of a [GoogleMap] with [id]. 22 | /// 23 | /// Mainly for internal use when instantiating a [GoogleMapController] passed 24 | /// in [GoogleMap.onMapCreated] callback. 25 | static Future init( 26 | int id, 27 | CameraPosition initialCameraPosition, 28 | _GoogleMapState googleMapState, 29 | ) async { 30 | await GoogleMapsFlutterPlatform.instance.init(id); 31 | return GoogleMapController._( 32 | googleMapState, 33 | mapId: id, 34 | ); 35 | } 36 | 37 | final _GoogleMapState _googleMapState; 38 | 39 | void _connectStreams(int mapId) { 40 | if (_googleMapState.widget.onCameraMoveStarted != null) { 41 | GoogleMapsFlutterPlatform.instance 42 | .onCameraMoveStarted(mapId: mapId) 43 | .listen((_) => _googleMapState.widget.onCameraMoveStarted!()); 44 | } 45 | if (_googleMapState.widget.onCameraMove != null) { 46 | GoogleMapsFlutterPlatform.instance.onCameraMove(mapId: mapId).listen( 47 | (CameraMoveEvent e) => 48 | _googleMapState.widget.onCameraMove!(e.value), 49 | ); 50 | } 51 | if (_googleMapState.widget.onCameraIdle != null) { 52 | GoogleMapsFlutterPlatform.instance 53 | .onCameraIdle(mapId: mapId) 54 | .listen((_) => _googleMapState.widget.onCameraIdle!()); 55 | } 56 | GoogleMapsFlutterPlatform.instance 57 | .onMarkerTap(mapId: mapId) 58 | .listen((MarkerTapEvent e) => _googleMapState.onMarkerTap(e.value)); 59 | GoogleMapsFlutterPlatform.instance.onMarkerDragStart(mapId: mapId).listen( 60 | (MarkerDragStartEvent e) => 61 | _googleMapState.onMarkerDragStart(e.value, e.position), 62 | ); 63 | GoogleMapsFlutterPlatform.instance.onMarkerDrag(mapId: mapId).listen( 64 | (MarkerDragEvent e) => 65 | _googleMapState.onMarkerDrag(e.value, e.position), 66 | ); 67 | GoogleMapsFlutterPlatform.instance.onMarkerDragEnd(mapId: mapId).listen( 68 | (MarkerDragEndEvent e) => 69 | _googleMapState.onMarkerDragEnd(e.value, e.position), 70 | ); 71 | GoogleMapsFlutterPlatform.instance.onInfoWindowTap(mapId: mapId).listen( 72 | (InfoWindowTapEvent e) => _googleMapState.onInfoWindowTap(e.value), 73 | ); 74 | GoogleMapsFlutterPlatform.instance 75 | .onPolylineTap(mapId: mapId) 76 | .listen((PolylineTapEvent e) => _googleMapState.onPolylineTap(e.value)); 77 | GoogleMapsFlutterPlatform.instance 78 | .onPolygonTap(mapId: mapId) 79 | .listen((PolygonTapEvent e) => _googleMapState.onPolygonTap(e.value)); 80 | GoogleMapsFlutterPlatform.instance 81 | .onCircleTap(mapId: mapId) 82 | .listen((CircleTapEvent e) => _googleMapState.onCircleTap(e.value)); 83 | GoogleMapsFlutterPlatform.instance 84 | .onTap(mapId: mapId) 85 | .listen((MapTapEvent e) => _googleMapState.onTap(e.position)); 86 | GoogleMapsFlutterPlatform.instance.onLongPress(mapId: mapId).listen( 87 | (MapLongPressEvent e) => _googleMapState.onLongPress(e.position), 88 | ); 89 | } 90 | 91 | /// Updates configuration options of the map user interface. 92 | /// 93 | /// Change listeners are notified once the update has been made on the 94 | /// platform side. 95 | /// 96 | /// The returned [Future] completes after listeners have been notified. 97 | Future _updateMapConfiguration(MapConfiguration update) { 98 | return GoogleMapsFlutterPlatform.instance 99 | .updateMapConfiguration(update, mapId: mapId); 100 | } 101 | 102 | /// Updates marker configuration. 103 | /// 104 | /// Change listeners are notified once the update has been made on the 105 | /// platform side. 106 | /// 107 | /// The returned [Future] completes after listeners have been notified. 108 | Future _updateMarkers(MarkerUpdates markerUpdates) { 109 | return GoogleMapsFlutterPlatform.instance 110 | .updateMarkers(markerUpdates, mapId: mapId); 111 | } 112 | 113 | /// Updates polygon configuration. 114 | /// 115 | /// Change listeners are notified once the update has been made on the 116 | /// platform side. 117 | /// 118 | /// The returned [Future] completes after listeners have been notified. 119 | Future _updatePolygons(PolygonUpdates polygonUpdates) { 120 | return GoogleMapsFlutterPlatform.instance 121 | .updatePolygons(polygonUpdates, mapId: mapId); 122 | } 123 | 124 | /// Updates polyline configuration. 125 | /// 126 | /// Change listeners are notified once the update has been made on the 127 | /// platform side. 128 | /// 129 | /// The returned [Future] completes after listeners have been notified. 130 | Future _updatePolylines(PolylineUpdates polylineUpdates) { 131 | return GoogleMapsFlutterPlatform.instance 132 | .updatePolylines(polylineUpdates, mapId: mapId); 133 | } 134 | 135 | /// Updates circle configuration. 136 | /// 137 | /// Change listeners are notified once the update has been made on the 138 | /// platform side. 139 | /// 140 | /// The returned [Future] completes after listeners have been notified. 141 | Future _updateCircles(CircleUpdates circleUpdates) { 142 | return GoogleMapsFlutterPlatform.instance 143 | .updateCircles(circleUpdates, mapId: mapId); 144 | } 145 | 146 | /// Updates tile overlays configuration. 147 | /// 148 | /// Change listeners are notified once the update has been made on the 149 | /// platform side. 150 | /// 151 | /// The returned [Future] completes after listeners have been notified. 152 | Future _updateTileOverlays(Set newTileOverlays) { 153 | return GoogleMapsFlutterPlatform.instance 154 | .updateTileOverlays(newTileOverlays: newTileOverlays, mapId: mapId); 155 | } 156 | 157 | /// Clears the tile cache so that all tiles will be requested again from the 158 | /// [TileProvider]. 159 | /// 160 | /// The current tiles from this tile overlay will also be 161 | /// cleared from the map after calling this method. The API maintains a small 162 | /// in-memory cache of tiles. If you want to cache tiles for longer, you 163 | /// should implement an on-disk cache. 164 | Future clearTileCache(TileOverlayId tileOverlayId) async { 165 | return GoogleMapsFlutterPlatform.instance 166 | .clearTileCache(tileOverlayId, mapId: mapId); 167 | } 168 | 169 | /// Starts an animated change of the map camera position. 170 | /// 171 | /// The returned [Future] completes after the change has been started on the 172 | /// platform side. 173 | Future animateCamera(CameraUpdate cameraUpdate) { 174 | return GoogleMapsFlutterPlatform.instance 175 | .animateCamera(cameraUpdate, mapId: mapId); 176 | } 177 | 178 | /// Changes the map camera position. 179 | /// 180 | /// The returned [Future] completes after the change has been made on the 181 | /// platform side. 182 | Future moveCamera(CameraUpdate cameraUpdate) { 183 | return GoogleMapsFlutterPlatform.instance 184 | .moveCamera(cameraUpdate, mapId: mapId); 185 | } 186 | 187 | /// Sets the styling of the base map. 188 | /// 189 | /// Set to `null` to clear any previous custom styling. 190 | /// 191 | /// If problems were detected with the [mapStyle], including un-parsable 192 | /// styling JSON, unrecognized feature type, unrecognized element type, or 193 | /// invalid styler keys: [MapStyleException] is thrown and the current 194 | /// style is left unchanged. 195 | /// 196 | /// The style string can be generated using [map style tool](https://mapstyle.withgoogle.com/). 197 | /// Also, refer [iOS](https://developers.google.com/maps/documentation/ios-sdk/style-reference) 198 | /// and [Android](https://developers.google.com/maps/documentation/android-sdk/style-reference) 199 | /// style reference for more information regarding the supported styles. 200 | @Deprecated('Use GoogleMap.style instead.') 201 | Future setMapStyle(String? mapStyle) { 202 | return GoogleMapsFlutterPlatform.instance 203 | .setMapStyle(mapStyle, mapId: mapId); 204 | } 205 | 206 | /// Returns the last style error, if any. 207 | Future getStyleError() { 208 | return GoogleMapsFlutterPlatform.instance.getStyleError(mapId: mapId); 209 | } 210 | 211 | /// Return [LatLngBounds] defining the region that is visible in a map. 212 | Future getVisibleRegion() { 213 | return GoogleMapsFlutterPlatform.instance.getVisibleRegion(mapId: mapId); 214 | } 215 | 216 | /// Return [ScreenCoordinate] of the [LatLng] in the current map view. 217 | /// 218 | /// A projection is used to translate between on screen location and geographic coordinates. 219 | /// Screen location is in screen pixels (not display pixels) with respect to the top left corner 220 | /// of the map, not necessarily of the whole screen. 221 | Future getScreenCoordinate(LatLng latLng) { 222 | return GoogleMapsFlutterPlatform.instance 223 | .getScreenCoordinate(latLng, mapId: mapId); 224 | } 225 | 226 | /// Returns [LatLng] corresponding to the [ScreenCoordinate] in the current map view. 227 | /// 228 | /// Returned [LatLng] corresponds to a screen location. The screen location is specified in screen 229 | /// pixels (not display pixels) relative to the top left of the map, not top left of the whole screen. 230 | Future getLatLng(ScreenCoordinate screenCoordinate) { 231 | return GoogleMapsFlutterPlatform.instance 232 | .getLatLng(screenCoordinate, mapId: mapId); 233 | } 234 | 235 | /// Programmatically show the Info Window for a [Marker]. 236 | /// 237 | /// The `markerId` must match one of the markers on the map. 238 | /// An invalid `markerId` triggers an "Invalid markerId" error. 239 | /// 240 | /// * See also: 241 | /// * [hideMarkerInfoWindow] to hide the Info Window. 242 | /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. 243 | Future showMarkerInfoWindow(MarkerId markerId) { 244 | return GoogleMapsFlutterPlatform.instance 245 | .showMarkerInfoWindow(markerId, mapId: mapId); 246 | } 247 | 248 | /// Programmatically hide the Info Window for a [Marker]. 249 | /// 250 | /// The `markerId` must match one of the markers on the map. 251 | /// An invalid `markerId` triggers an "Invalid markerId" error. 252 | /// 253 | /// * See also: 254 | /// * [showMarkerInfoWindow] to show the Info Window. 255 | /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. 256 | Future hideMarkerInfoWindow(MarkerId markerId) { 257 | return GoogleMapsFlutterPlatform.instance 258 | .hideMarkerInfoWindow(markerId, mapId: mapId); 259 | } 260 | 261 | /// Returns `true` when the [InfoWindow] is showing, `false` otherwise. 262 | /// 263 | /// The `markerId` must match one of the markers on the map. 264 | /// An invalid `markerId` triggers an "Invalid markerId" error. 265 | /// 266 | /// * See also: 267 | /// * [showMarkerInfoWindow] to show the Info Window. 268 | /// * [hideMarkerInfoWindow] to hide the Info Window. 269 | Future isMarkerInfoWindowShown(MarkerId markerId) { 270 | return GoogleMapsFlutterPlatform.instance 271 | .isMarkerInfoWindowShown(markerId, mapId: mapId); 272 | } 273 | 274 | /// Returns the current zoom level of the map 275 | Future getZoomLevel() { 276 | return GoogleMapsFlutterPlatform.instance.getZoomLevel(mapId: mapId); 277 | } 278 | 279 | /// Returns the image bytes of the map 280 | Future takeSnapshot() { 281 | return GoogleMapsFlutterPlatform.instance.takeSnapshot(mapId: mapId); 282 | } 283 | 284 | /// Disposes of the platform resources 285 | void dispose() { 286 | GoogleMapsFlutterPlatform.instance.dispose(mapId: mapId); 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/lib/src/google_maps_bitmap_descriptor.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 5 | import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart' 6 | as google_maps; 7 | 8 | class GoogleMapsPlatformBitmapDescriptor extends PlatformBitmapDescriptor { 9 | GoogleMapsPlatformBitmapDescriptor() : super.implementation(); 10 | @override 11 | Future fromAssetImage( 12 | ImageConfiguration configuration, 13 | String assetName, { 14 | AssetBundle? bundle, 15 | String? package, 16 | }) async { 17 | final descriptor = await google_maps.BitmapDescriptor.fromAssetImage( 18 | configuration, 19 | assetName, 20 | bundle: bundle, 21 | package: package, 22 | ); 23 | return GoogleMapsBitmapDescriptor(descriptor); 24 | } 25 | 26 | @override 27 | GoogleMapsBitmapDescriptor fromBytes(Uint8List byteData) { 28 | return GoogleMapsBitmapDescriptor( 29 | google_maps.BitmapDescriptor.fromBytes(byteData), 30 | ); 31 | } 32 | } 33 | 34 | class GoogleMapsBitmapDescriptor extends BitmapDescriptor { 35 | GoogleMapsBitmapDescriptor(this.descriptor); 36 | google_maps.BitmapDescriptor descriptor; 37 | } 38 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/lib/src/google_maps_camera_update.dart: -------------------------------------------------------------------------------- 1 | import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart' 2 | as google_maps; 3 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 4 | import 'package:platform_maps_flutter_google_android/src/mapper_extensions.dart'; 5 | 6 | class GoogleMapsPlatformCameraUpdate extends PlatformCameraUpdate { 7 | GoogleMapsPlatformCameraUpdate() : super.implementation(); 8 | 9 | @override 10 | CameraUpdate newCameraPosition(CameraPosition cameraPosition) { 11 | return GoogleMapsCameraUpdate._( 12 | google_maps.CameraUpdate.newCameraPosition( 13 | cameraPosition.googleMapsCameraPosition, 14 | ), 15 | ); 16 | } 17 | 18 | @override 19 | CameraUpdate newLatLng(LatLng latLng) { 20 | return GoogleMapsCameraUpdate._( 21 | google_maps.CameraUpdate.newLatLng( 22 | latLng.googleMapsLatLng, 23 | ), 24 | ); 25 | } 26 | 27 | @override 28 | CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) { 29 | return GoogleMapsCameraUpdate._( 30 | google_maps.CameraUpdate.newLatLngBounds( 31 | bounds.googleMapsLatLngBounds, 32 | padding, 33 | ), 34 | ); 35 | } 36 | 37 | @override 38 | CameraUpdate newLatLngZoom(LatLng latLng, double zoom) { 39 | return GoogleMapsCameraUpdate._( 40 | google_maps.CameraUpdate.newLatLngZoom( 41 | latLng.googleMapsLatLng, 42 | zoom, 43 | ), 44 | ); 45 | } 46 | 47 | @override 48 | CameraUpdate zoomBy(double amount) { 49 | return GoogleMapsCameraUpdate._( 50 | google_maps.CameraUpdate.zoomBy(amount), 51 | ); 52 | } 53 | 54 | @override 55 | CameraUpdate zoomIn() { 56 | return GoogleMapsCameraUpdate._( 57 | google_maps.CameraUpdate.zoomIn(), 58 | ); 59 | } 60 | 61 | @override 62 | CameraUpdate zoomOut() { 63 | return GoogleMapsCameraUpdate._( 64 | google_maps.CameraUpdate.zoomOut(), 65 | ); 66 | } 67 | 68 | @override 69 | CameraUpdate zoomTo(double zoom) { 70 | return GoogleMapsCameraUpdate._( 71 | google_maps.CameraUpdate.zoomTo(zoom), 72 | ); 73 | } 74 | } 75 | 76 | class GoogleMapsCameraUpdate extends CameraUpdate { 77 | const GoogleMapsCameraUpdate._(this.googleMapsCameraUpdate); 78 | final google_maps.CameraUpdate googleMapsCameraUpdate; 79 | } 80 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/lib/src/google_maps_platform_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:platform_maps_flutter_google_android/src/google_map_original.dart' 4 | as google_map_original; 5 | import 'package:platform_maps_flutter_google_android/src/google_maps_camera_update.dart'; 6 | import 'package:platform_maps_flutter_google_android/src/mapper_extensions.dart'; 7 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 8 | 9 | class GoogleMapsPlatformController extends PlatformMapsPlatformController { 10 | GoogleMapsPlatformController(this._googleMapController); 11 | final google_map_original.GoogleMapController _googleMapController; 12 | 13 | @override 14 | Future animateCamera(CameraUpdate cameraUpdate) { 15 | if (cameraUpdate is GoogleMapsCameraUpdate) { 16 | return _googleMapController 17 | .animateCamera(cameraUpdate.googleMapsCameraUpdate); 18 | } 19 | throw UnsupportedError( 20 | 'GoogleMapsPlatformController: animateCamera - cameraUpdate is not a GoogleMapsCameraUpdate\n${cameraUpdate.toString()}', 21 | ); 22 | } 23 | 24 | @override 25 | Future getVisibleRegion() async { 26 | final visibleRegion = await _googleMapController.getVisibleRegion(); 27 | return visibleRegion.platformLatLngBounds; 28 | } 29 | 30 | @override 31 | Future hideMarkerInfoWindow(MarkerId markerId) { 32 | return _googleMapController 33 | .hideMarkerInfoWindow(markerId.googleMapsMarkerId); 34 | } 35 | 36 | @override 37 | Future isMarkerInfoWindowShown(MarkerId markerId) { 38 | return _googleMapController 39 | .isMarkerInfoWindowShown(markerId.googleMapsMarkerId); 40 | } 41 | 42 | @override 43 | Future moveCamera(CameraUpdate cameraUpdate) { 44 | if (cameraUpdate is GoogleMapsCameraUpdate) { 45 | return _googleMapController 46 | .moveCamera(cameraUpdate.googleMapsCameraUpdate); 47 | } 48 | throw UnsupportedError( 49 | 'GoogleMapsPlatformController: moveCamera - cameraUpdate is not a GoogleMapsCameraUpdate\n${cameraUpdate.toString()}', 50 | ); 51 | } 52 | 53 | @override 54 | Future showMarkerInfoWindow(MarkerId markerId) { 55 | return _googleMapController 56 | .showMarkerInfoWindow(markerId.googleMapsMarkerId); 57 | } 58 | 59 | @override 60 | Future takeSnapshot() { 61 | return _googleMapController.takeSnapshot(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/lib/src/google_maps_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/gestures.dart'; 3 | import 'package:flutter/widgets.dart'; 4 | import 'package:platform_maps_flutter_google_android/src/mapper_extensions.dart'; 5 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 6 | import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart' 7 | as google_maps; 8 | import 'package:platform_maps_flutter_google_android/src/google_map_original.dart' 9 | as google_map_original; 10 | 11 | class GoogleMapsWidget extends PlatformMapsPlatformWidget { 12 | GoogleMapsWidget(PlatformMapsPlatformWidgetCreationParams params) 13 | : super.implementation(params); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return _PlatformMap(params: params); 18 | } 19 | } 20 | 21 | class _PlatformMap extends StatefulWidget { 22 | const _PlatformMap({ 23 | required this.params, 24 | }); 25 | 26 | final PlatformMapsPlatformWidgetCreationParams params; 27 | 28 | /// Callback method for when the map is ready to be used. 29 | /// 30 | /// Used to receive a [GoogleMapController] for this [GoogleMap]. 31 | MapCreatedCallback? get onMapCreated => params.onMapCreated; 32 | 33 | /// The initial position of the map's camera. 34 | CameraPosition get initialCameraPosition => params.initialCameraPosition; 35 | 36 | /// True if the map should show a compass when rotated. 37 | bool get compassEnabled => params.compassEnabled; 38 | 39 | /// Type of map tiles to be rendered. 40 | MapType get mapType => params.mapType; 41 | 42 | /// Preferred bounds for the camera zoom level. 43 | /// 44 | /// Actual bounds depend on map data and device. 45 | MinMaxZoomPreference get minMaxZoomPreference => params.minMaxZoomPreference; 46 | 47 | /// True if the map view should respond to rotate gestures. 48 | bool get rotateGesturesEnabled => params.rotateGesturesEnabled; 49 | 50 | /// True if the map view should respond to scroll gestures. 51 | bool get scrollGesturesEnabled => params.scrollGesturesEnabled; 52 | 53 | /// True if the map view should show zoom controls. This includes two buttons 54 | /// to zoom in and zoom out. The default value is to show zoom controls. 55 | /// 56 | /// This is only supported on Android. And this field is silently ignored on iOS. 57 | bool get zoomControlsEnabled => params.zoomControlsEnabled; 58 | 59 | /// True if the map view should respond to zoom gestures. 60 | bool get zoomGesturesEnabled => params.zoomGesturesEnabled; 61 | 62 | /// True if the map view should respond to tilt gestures. 63 | bool get tiltGesturesEnabled => params.tiltGesturesEnabled; 64 | 65 | /// Padding to be set on map. See https://developers.google.com/maps/documentation/android-sdk/map#map_padding for more details. 66 | EdgeInsets get padding => params.padding; 67 | 68 | /// Markers to be placed on the map. 69 | Set get markers => params.markers; 70 | 71 | /// Polygons to be placed on the map. 72 | Set get polygons => params.polygons; 73 | 74 | /// Polylines to be placed on the map. 75 | Set get polylines => params.polylines; 76 | 77 | /// Circles to be placed on the map. 78 | Set get circles => params.circles; 79 | 80 | /// Called when the camera starts moving. 81 | /// 82 | /// This can be initiated by the following: 83 | /// 1. Non-gesture animation initiated in response to user actions. 84 | /// For example: zoom buttons, my location button, or marker clicks. 85 | /// 2. Programmatically initiated animation. 86 | /// 3. Camera motion initiated in response to user gestures on the map. 87 | /// For example: pan, tilt, pinch to zoom, or rotate. 88 | VoidCallback? get onCameraMoveStarted => params.onCameraMoveStarted; 89 | 90 | /// Called repeatedly as the camera continues to move after an 91 | /// onCameraMoveStarted call. 92 | /// 93 | /// This may be called as often as once every frame and should 94 | /// not perform expensive operations. 95 | CameraPositionCallback? get onCameraMove => params.onCameraMove; 96 | 97 | /// Called when camera movement has ended, there are no pending 98 | /// animations and the user has stopped interacting with the map. 99 | VoidCallback? get onCameraIdle => params.onCameraIdle; 100 | 101 | /// Called every time a [GoogleMap] is tapped. 102 | ArgumentCallback? get onTap => params.onTap; 103 | 104 | /// Called every time a [GoogleMap] is long pressed. 105 | ArgumentCallback? get onLongPress => params.onLongPress; 106 | 107 | /// True if a "My Location" layer should be shown on the map. 108 | /// 109 | /// This layer includes a location indicator at the current device location, 110 | /// as well as a My Location button. 111 | /// * The indicator is a small blue dot if the device is stationary, or a 112 | /// chevron if the device is moving. 113 | /// * The My Location button animates to focus on the user's current location 114 | /// if the user's location is currently known. 115 | /// 116 | /// Enabling this feature requires adding location permissions to both native 117 | /// platforms of your app. 118 | /// * On Android add either 119 | /// `` 120 | /// or `` 121 | /// to your `AndroidManifest.xml` file. `ACCESS_COARSE_LOCATION` returns a 122 | /// location with an accuracy approximately equivalent to a city block, while 123 | /// `ACCESS_FINE_LOCATION` returns as precise a location as possible, although 124 | /// it consumes more battery power. You will also need to request these 125 | /// permissions during run-time. If they are not granted, the My Location 126 | /// feature will fail silently. 127 | /// * On iOS add a `NSLocationWhenInUseUsageDescription` key to your 128 | /// `Info.plist` file. This will automatically prompt the user for permissions 129 | /// when the map tries to turn on the My Location layer. 130 | bool get myLocationEnabled => params.myLocationEnabled; 131 | 132 | /// Enables or disables the my-location button. 133 | /// 134 | /// The my-location button causes the camera to move such that the user's 135 | /// location is in the center of the map. If the button is enabled, it is 136 | /// only shown when the my-location layer is enabled. 137 | /// 138 | /// By default, the my-location button is enabled (and hence shown when the 139 | /// my-location layer is enabled). 140 | /// 141 | /// See also: 142 | /// * [myLocationEnabled] parameter. 143 | bool get myLocationButtonEnabled => params.myLocationButtonEnabled; 144 | 145 | /// Enables or disables the traffic layer of the map 146 | bool get trafficEnabled => params.trafficEnabled; 147 | 148 | /// Which gestures should be consumed by the map. 149 | /// 150 | /// It is possible for other gesture recognizers to be competing with the map on pointer 151 | /// events, e.g if the map is inside a [ListView] the [ListView] will want to handle 152 | /// vertical drags. The map will claim gestures that are recognized by any of the 153 | /// recognizers on this list. 154 | /// 155 | /// When this set is empty, the map will only handle pointer events for gestures that 156 | /// were not claimed by any other gesture recognizer. 157 | Set> get gestureRecognizers => 158 | params.gestureRecognizers; 159 | @override 160 | _PlatformMapState createState() => _PlatformMapState(); 161 | } 162 | 163 | class _PlatformMapState extends State<_PlatformMap> { 164 | @override 165 | Widget build(BuildContext context) { 166 | return google_map_original.GoogleMap( 167 | initialCameraPosition: 168 | widget.initialCameraPosition.googleMapsCameraPosition, 169 | compassEnabled: widget.compassEnabled, 170 | mapType: _getGoogleMapType(), 171 | padding: widget.padding, 172 | markers: widget.markers.googleMapsMarkerSet, 173 | polylines: widget.polylines.googleMapsPolylineSet, 174 | polygons: widget.polygons.googleMapsPolygonSet, 175 | circles: widget.circles.googleMapsCircleSet, 176 | gestureRecognizers: widget.gestureRecognizers, 177 | onCameraIdle: widget.onCameraIdle, 178 | myLocationButtonEnabled: widget.myLocationButtonEnabled, 179 | myLocationEnabled: widget.myLocationEnabled, 180 | onCameraMoveStarted: widget.onCameraMoveStarted, 181 | tiltGesturesEnabled: widget.tiltGesturesEnabled, 182 | rotateGesturesEnabled: widget.rotateGesturesEnabled, 183 | zoomControlsEnabled: widget.zoomControlsEnabled, 184 | zoomGesturesEnabled: widget.zoomGesturesEnabled, 185 | scrollGesturesEnabled: widget.scrollGesturesEnabled, 186 | onMapCreated: _onMapCreated, 187 | onCameraMove: _onCameraMove, 188 | onTap: _onTap, 189 | onLongPress: _onLongPress, 190 | trafficEnabled: widget.trafficEnabled, 191 | minMaxZoomPreference: 192 | widget.minMaxZoomPreference.googleMapsZoomPreference, 193 | ); 194 | } 195 | 196 | void _onMapCreated(google_map_original.GoogleMapController controller) { 197 | widget.onMapCreated?.call(controller.platformMapController); 198 | } 199 | 200 | void _onCameraMove(google_maps.CameraPosition cameraPosition) { 201 | widget.onCameraMove?.call(cameraPosition.platformCameraPosition); 202 | } 203 | 204 | void _onTap(google_maps.LatLng position) { 205 | widget.onTap?.call(position.platformLatLng); 206 | } 207 | 208 | void _onLongPress(google_maps.LatLng position) { 209 | widget.onLongPress?.call(position.platformLatLng); 210 | } 211 | 212 | google_maps.MapType _getGoogleMapType() { 213 | switch (widget.mapType) { 214 | case MapType.normal: 215 | return google_maps.MapType.normal; 216 | case MapType.satellite: 217 | return google_maps.MapType.satellite; 218 | case MapType.hybrid: 219 | return google_maps.MapType.hybrid; 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/lib/src/mapper_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart' 4 | as google_maps; 5 | import 'package:platform_maps_flutter_google_android/src/google_maps_bitmap_descriptor.dart'; 6 | import 'package:platform_maps_flutter_google_android/src/google_maps_platform_controller.dart'; 7 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 8 | 9 | import 'package:platform_maps_flutter_google_android/src/google_map_original.dart' 10 | as google_map_original; 11 | 12 | extension GoogleMapsLatLngMapper on google_maps.LatLng { 13 | LatLng get platformLatLng { 14 | return LatLng(latitude, longitude); 15 | } 16 | } 17 | 18 | extension LatLngMapper on LatLng { 19 | google_maps.LatLng get googleMapsLatLng { 20 | return google_maps.LatLng(latitude, longitude); 21 | } 22 | } 23 | 24 | extension on List { 25 | List get googleLatLngList { 26 | return map((latLng) => latLng.googleMapsLatLng).toList(); 27 | } 28 | } 29 | 30 | extension LatLngBoundsMapper on LatLngBounds { 31 | google_maps.LatLngBounds get googleMapsLatLngBounds { 32 | return google_maps.LatLngBounds( 33 | southwest: southwest.googleMapsLatLng, 34 | northeast: northeast.googleMapsLatLng, 35 | ); 36 | } 37 | } 38 | 39 | extension GoogleMapsLatLngBoundsMapper on google_maps.LatLngBounds { 40 | LatLngBounds get platformLatLngBounds { 41 | return LatLngBounds( 42 | southwest: southwest.platformLatLng, 43 | northeast: northeast.platformLatLng, 44 | ); 45 | } 46 | } 47 | 48 | extension MarkersMapper on Set { 49 | Set get googleMapsMarkerSet { 50 | return map((marker) => marker.googleMapsMarker).toSet(); 51 | } 52 | } 53 | 54 | extension on Marker { 55 | google_maps.Marker get googleMapsMarker { 56 | return google_maps.Marker( 57 | markerId: markerId.googleMapsMarkerId, 58 | alpha: alpha, 59 | anchor: anchor, 60 | draggable: draggable, 61 | infoWindow: infoWindow.googleMapsInfoWindow, 62 | onTap: onTap, 63 | icon: (icon as GoogleMapsBitmapDescriptor?)?.descriptor ?? 64 | google_maps.BitmapDescriptor.defaultMarker, 65 | visible: visible, 66 | onDragEnd: onDragEnd != null 67 | ? (google_maps.LatLng latLng) => 68 | _onGoogleMarkerDragEnd(latLng, onDragEnd) 69 | : null, 70 | position: position.googleMapsLatLng, 71 | ); 72 | } 73 | 74 | static _onGoogleMarkerDragEnd( 75 | google_maps.LatLng latLng, 76 | Function? onDragEnd, 77 | ) { 78 | onDragEnd?.call(latLng.platformLatLng); 79 | } 80 | } 81 | 82 | extension MarkerIdMapper on MarkerId { 83 | google_maps.MarkerId get googleMapsMarkerId { 84 | return google_maps.MarkerId(value); 85 | } 86 | } 87 | 88 | extension on InfoWindow { 89 | google_maps.InfoWindow get googleMapsInfoWindow => google_maps.InfoWindow( 90 | anchor: anchor ?? const Offset(0, 0), 91 | onTap: onTap, 92 | snippet: snippet, 93 | title: title, 94 | ); 95 | } 96 | 97 | extension CameraMapper on CameraPosition { 98 | google_maps.CameraPosition get googleMapsCameraPosition { 99 | return google_maps.CameraPosition( 100 | target: target.googleMapsLatLng, 101 | bearing: bearing, 102 | tilt: tilt, 103 | zoom: zoom, 104 | ); 105 | } 106 | } 107 | 108 | extension GoogleMapsCameraMapper on google_maps.CameraPosition { 109 | CameraPosition get platformCameraPosition { 110 | return CameraPosition( 111 | target: target.platformLatLng, 112 | bearing: bearing, 113 | tilt: tilt, 114 | zoom: zoom, 115 | ); 116 | } 117 | } 118 | 119 | extension PolylinesMapper on Set { 120 | Set get googleMapsPolylineSet { 121 | return map((polyline) => polyline.googleMapsPolyline).toSet(); 122 | } 123 | } 124 | 125 | extension on Polyline { 126 | google_maps.Polyline get googleMapsPolyline { 127 | return google_maps.Polyline( 128 | polylineId: polylineId.googleMapsPolylineId, 129 | color: color, 130 | consumeTapEvents: consumeTapEvents, 131 | startCap: polylineCap.googlePolylineCap, 132 | endCap: polylineCap.googlePolylineCap, 133 | jointType: jointType.googleMapsJointType, 134 | onTap: onTap, 135 | patterns: patterns.googleMapsPatternItemList, 136 | points: points.googleLatLngList, 137 | visible: visible, 138 | width: width, 139 | ); 140 | } 141 | } 142 | 143 | extension on PolylineId { 144 | google_maps.PolylineId get googleMapsPolylineId { 145 | return google_maps.PolylineId(value); 146 | } 147 | } 148 | 149 | extension on Cap { 150 | static const Map googleMapsCaps = { 151 | Cap.buttCap: google_maps.Cap.buttCap, 152 | Cap.roundCap: google_maps.Cap.roundCap, 153 | Cap.squareCap: google_maps.Cap.squareCap, 154 | }; 155 | 156 | google_maps.Cap get googlePolylineCap { 157 | return googleMapsCaps[this]!; 158 | } 159 | } 160 | 161 | extension on JointType { 162 | static const List googleMapsJointTypes = [ 163 | google_maps.JointType.mitered, 164 | google_maps.JointType.bevel, 165 | google_maps.JointType.round, 166 | ]; 167 | 168 | google_maps.JointType get googleMapsJointType { 169 | return googleMapsJointTypes[value]; 170 | } 171 | } 172 | 173 | extension on List { 174 | List get googleMapsPatternItemList { 175 | return map((patternItem) => patternItem.googleMapsPatternItem).toList(); 176 | } 177 | } 178 | 179 | extension on PatternItem { 180 | google_maps.PatternItem get googleMapsPatternItem { 181 | return switch (this) { 182 | DotPatternItem() => google_maps.PatternItem.dot, 183 | DashPatternItem dash => google_maps.PatternItem.dash(dash.length), 184 | GapPatternItem gap => google_maps.PatternItem.gap(gap.length), 185 | }; 186 | } 187 | } 188 | 189 | extension PolygonMapper on Set { 190 | Set get googleMapsPolygonSet { 191 | return map((polygon) => polygon.googleMapsPolygon).toSet(); 192 | } 193 | } 194 | 195 | extension on Polygon { 196 | google_maps.Polygon get googleMapsPolygon { 197 | return google_maps.Polygon( 198 | polygonId: google_maps.PolygonId(polygonId.value), 199 | consumeTapEvents: consumeTapEvents, 200 | fillColor: fillColor, 201 | onTap: onTap, 202 | points: points.googleLatLngList, 203 | strokeColor: strokeColor, 204 | strokeWidth: strokeWidth, 205 | visible: visible, 206 | ); 207 | } 208 | } 209 | 210 | extension CircleMapper on Set { 211 | Set get googleMapsCircleSet { 212 | return map((circle) => circle.googleMapsCircle).toSet(); 213 | } 214 | } 215 | 216 | extension on Circle { 217 | google_maps.Circle get googleMapsCircle { 218 | return google_maps.Circle( 219 | circleId: google_maps.CircleId(circleId.value), 220 | consumeTapEvents: consumeTapEvents, 221 | fillColor: fillColor, 222 | onTap: onTap, 223 | center: center.googleMapsLatLng, 224 | radius: radius, 225 | strokeColor: strokeColor, 226 | strokeWidth: strokeWidth, 227 | visible: visible, 228 | ); 229 | } 230 | } 231 | 232 | extension ZoomMapper on MinMaxZoomPreference { 233 | google_maps.MinMaxZoomPreference get googleMapsZoomPreference { 234 | return google_maps.MinMaxZoomPreference(minZoom, maxZoom); 235 | } 236 | } 237 | 238 | extension GoogleMapsControllerMappers 239 | on google_map_original.GoogleMapController { 240 | PlatformMapController get platformMapController { 241 | return PlatformMapController(GoogleMapsPlatformController(this)); 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: platform_maps_flutter_google_android 2 | description: Android Google Maps implementation for the platform_maps_flutter plugin. 3 | version: 1.0.0-beta 4 | homepage: https://github.com/albert-heijn-technology 5 | repository: https://github.com/albert-heijn-technology/platform_maps_flutter/tree/master/packages/platform_maps_flutter_google_android 6 | issue_tracker: https://github.com/albert-heijn-technology/platform_maps_flutter/issues 7 | 8 | environment: 9 | sdk: '>=3.2.4 <4.0.0' 10 | flutter: ">=1.17.0" 11 | 12 | flutter: 13 | plugin: 14 | implements: platform_maps_flutter 15 | platforms: 16 | android: 17 | dartPluginClass: PlatformMapsGoogleAndroid 18 | fileName: platform_maps_flutter_google.dart 19 | 20 | dependencies: 21 | flutter: 22 | sdk: flutter 23 | google_maps_flutter_android: ^2.7.0 24 | google_maps_flutter_platform_interface: ^2.6.0 25 | platform_maps_flutter_platform_interface: ^1.0.0-beta 26 | 27 | dev_dependencies: 28 | flutter_test: 29 | sdk: flutter 30 | flutter_lints: ^2.0.0 31 | 32 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_google_android/test/platform_maps_flutter_google_android_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter_test/flutter_test.dart'; 4 | import 'package:platform_maps_flutter_google_android/platform_maps_flutter_google_android.dart'; 5 | import 'package:platform_maps_flutter_google_android/src/google_maps_bitmap_descriptor.dart'; 6 | import 'package:platform_maps_flutter_google_android/src/google_maps_camera_update.dart'; 7 | import 'package:platform_maps_flutter_google_android/src/google_maps_widget.dart'; 8 | 9 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 10 | 11 | void main() { 12 | test('Verify widget generation', () { 13 | PlatformMapsGoogleAndroid.registerWith(); 14 | 15 | final widget = PlatformMapsPlatformWidget( 16 | const PlatformMapsPlatformWidgetCreationParams( 17 | initialCameraPosition: CameraPosition(target: LatLng(0, 0)), 18 | ), 19 | ); 20 | expect(widget, isA()); 21 | }); 22 | 23 | test('Verify bitmap descriptor generation', () { 24 | PlatformMapsGoogleAndroid.registerWith(); 25 | 26 | final platformBitmapDescriptor = PlatformBitmapDescriptor(); 27 | expect(platformBitmapDescriptor, isA()); 28 | 29 | final bitmapDescriptor = 30 | platformBitmapDescriptor.fromBytes(Uint8List.fromList([1, 2])); 31 | expect(bitmapDescriptor, isA()); 32 | }); 33 | 34 | test('Verify camera update generation', () { 35 | PlatformMapsGoogleAndroid.registerWith(); 36 | 37 | final platformCameraUpdate = PlatformCameraUpdate(); 38 | expect(platformCameraUpdate, isA()); 39 | 40 | final cameraUpdate = platformCameraUpdate.zoomIn(); 41 | expect(cameraUpdate, isA()); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | 5 | # Avoid committing pubspec.lock for library packages; see 6 | # https://dart.dev/guides/libraries/private-files#pubspeclock. 7 | pubspec.lock 8 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0-beta.1 2 | 3 | * Fix: onMapCreated not being called 4 | 5 | ## 1.0.0-beta 6 | 7 | * Initial version, based on platform_maps_flutter 1.0.2 8 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2024, Albert Heijn Technology 4 | Copyright (c) 2019, Luis Thein 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/README.md: -------------------------------------------------------------------------------- 1 | # platform_maps_flutter_platform_interface 2 | 3 | A common platform interface for the `platform_maps_flutter` plugin. 4 | 5 | This interface allows platform-specific implementations of the `platform_maps_flutter` 6 | plugin, as well as the plugin itself, to ensure they are supporting the 7 | same interface. 8 | 9 | # Usage 10 | 11 | To implement a new platform-specific implementation of `platform_maps_flutter`, extend 12 | `PlatformMapsPlatform` with an implementation that performs the 13 | platform-specific behavior, and when you register your plugin, set the default 14 | `PlatformMapsPlatform` by calling 15 | `PlatformMapsPlatform.instance = MyCustomPlatformMapsPlatform()`. 16 | 17 | # Note on breaking changes 18 | 19 | Strongly prefer non-breaking changes (such as adding a method to the interface) 20 | over breaking changes for this package. 21 | 22 | See https://flutter.dev/go/platform-interface-breaking-changes for a discussion 23 | on why a less-clean interface is preferable to a breaking change. 24 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | - always_declare_return_types 6 | - avoid_annotating_with_dynamic 7 | - avoid_dynamic_calls 8 | - require_trailing_commas 9 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/platform_maps_flutter_platform_interface.dart: -------------------------------------------------------------------------------- 1 | export 'src/platform_maps_platform_widget.dart'; 2 | export 'src/platform_maps_platform_controller.dart'; 3 | export 'src/platform_maps_platform.dart'; 4 | export 'src/types.dart'; 5 | export 'src/platform_bitmap_descriptor.dart'; 6 | export 'src/platform_camera_update.dart'; 7 | export 'src/platform_map.dart'; 8 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/platform_bitmap_descriptor.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 5 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 6 | 7 | abstract class PlatformBitmapDescriptor extends PlatformInterface { 8 | /// Creates a new [PlatformBitmapDescriptor] 9 | factory PlatformBitmapDescriptor() { 10 | assert( 11 | PlatformMapsPlatform.instance != null, 12 | 'A platform implementation for `platform_maps_flutter` has not been set. Please ' 13 | 'ensure that an implementation of `PlatformMapsPlatform` has been set to ' 14 | '`PlatformMapsPlatform.instance` before use. For unit testing, ' 15 | '`PlatformMapsPlatform.instance` can be set with your own test implementation.', 16 | ); 17 | final PlatformBitmapDescriptor bitmapDescriptorDelegate = 18 | PlatformMapsPlatform.instance!.createBitmapDescriptor(); 19 | PlatformInterface.verify(bitmapDescriptorDelegate, _token); 20 | return bitmapDescriptorDelegate; 21 | } 22 | 23 | /// Used by the platform implementation to create a new 24 | /// [PlatformBitmapDescriptor]. 25 | /// 26 | /// Should only be used by platform implementations because they can't extend 27 | /// a class that only contains a factory constructor. 28 | @protected 29 | PlatformBitmapDescriptor.implementation() : super(token: _token); 30 | 31 | static final Object _token = Object(); 32 | 33 | Future fromAssetImage( 34 | ImageConfiguration configuration, 35 | String assetName, { 36 | AssetBundle? bundle, 37 | String? package, 38 | }); 39 | 40 | BitmapDescriptor fromBytes(Uint8List byteData); 41 | } 42 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/platform_camera_update.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 3 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 4 | 5 | abstract class PlatformCameraUpdate extends PlatformInterface { 6 | /// Creates a new [PlatformCameraUpdate] 7 | factory PlatformCameraUpdate() { 8 | assert( 9 | PlatformMapsPlatform.instance != null, 10 | 'A platform implementation for `platform_maps_flutter` has not been set. Please ' 11 | 'ensure that an implementation of `PlatformMapsPlatform` has been set to ' 12 | '`PlatformMapsPlatform.instance` before use. For unit testing, ' 13 | '`PlatformMapsPlatform.instance` can be set with your own test implementation.', 14 | ); 15 | final PlatformCameraUpdate cameraUpdateDelegate = 16 | PlatformMapsPlatform.instance!.createPlatformCameraUpdate(); 17 | PlatformInterface.verify(cameraUpdateDelegate, _token); 18 | return cameraUpdateDelegate; 19 | } 20 | 21 | @protected 22 | PlatformCameraUpdate.implementation() : super(token: _token); 23 | 24 | static final Object _token = Object(); 25 | 26 | CameraUpdate newCameraPosition(CameraPosition cameraPosition); 27 | CameraUpdate newLatLng(LatLng latLng); 28 | CameraUpdate newLatLngZoom(LatLng latLng, double zoom); 29 | CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding); 30 | CameraUpdate zoomBy(double amount); 31 | CameraUpdate zoomIn(); 32 | CameraUpdate zoomOut(); 33 | CameraUpdate zoomTo(double zoom); 34 | } 35 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/platform_map.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/gestures.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 5 | 6 | class PlatformMap extends StatelessWidget { 7 | PlatformMap({ 8 | super.key, 9 | required this.initialCameraPosition, 10 | this.onMapCreated, 11 | this.gestureRecognizers = const >{}, 12 | this.compassEnabled = true, 13 | this.mapType = MapType.normal, 14 | this.minMaxZoomPreference = MinMaxZoomPreference.unbounded, 15 | this.rotateGesturesEnabled = true, 16 | this.scrollGesturesEnabled = true, 17 | this.zoomControlsEnabled = true, 18 | this.zoomGesturesEnabled = true, 19 | this.tiltGesturesEnabled = true, 20 | this.myLocationEnabled = false, 21 | this.myLocationButtonEnabled = false, 22 | this.padding = const EdgeInsets.all(0), 23 | this.trafficEnabled = false, 24 | this.markers = const {}, 25 | this.polygons = const {}, 26 | this.polylines = const {}, 27 | this.circles = const {}, 28 | this.onCameraMoveStarted, 29 | this.onCameraMove, 30 | this.onCameraIdle, 31 | this.onTap, 32 | this.onLongPress, 33 | }) : _platform = PlatformMapsPlatformWidget( 34 | PlatformMapsPlatformWidgetCreationParams( 35 | compassEnabled: compassEnabled, 36 | gestureRecognizers: gestureRecognizers, 37 | initialCameraPosition: initialCameraPosition, 38 | mapType: mapType, 39 | minMaxZoomPreference: minMaxZoomPreference, 40 | myLocationButtonEnabled: myLocationButtonEnabled, 41 | myLocationEnabled: myLocationEnabled, 42 | onCameraIdle: onCameraIdle, 43 | onCameraMove: onCameraMove, 44 | onCameraMoveStarted: onCameraMoveStarted, 45 | onLongPress: onLongPress, 46 | onMapCreated: onMapCreated, 47 | onTap: onTap, 48 | padding: padding, 49 | polylines: polylines, 50 | polygons: polygons, 51 | circles: circles, 52 | markers: markers, 53 | rotateGesturesEnabled: rotateGesturesEnabled, 54 | scrollGesturesEnabled: scrollGesturesEnabled, 55 | tiltGesturesEnabled: tiltGesturesEnabled, 56 | trafficEnabled: trafficEnabled, 57 | zoomControlsEnabled: zoomControlsEnabled, 58 | zoomGesturesEnabled: zoomGesturesEnabled, 59 | ), 60 | ); 61 | 62 | /// Callback method for when the map is ready to be used. 63 | /// 64 | /// Used to receive a [GoogleMapController] for this [GoogleMap]. 65 | final MapCreatedCallback? onMapCreated; 66 | 67 | /// The initial position of the map's camera. 68 | final CameraPosition initialCameraPosition; 69 | 70 | /// True if the map should show a compass when rotated. 71 | final bool compassEnabled; 72 | 73 | /// Type of map tiles to be rendered. 74 | final MapType mapType; 75 | 76 | /// Preferred bounds for the camera zoom level. 77 | /// 78 | /// Actual bounds depend on map data and device. 79 | final MinMaxZoomPreference minMaxZoomPreference; 80 | 81 | /// True if the map view should respond to rotate gestures. 82 | final bool rotateGesturesEnabled; 83 | 84 | /// True if the map view should respond to scroll gestures. 85 | final bool scrollGesturesEnabled; 86 | 87 | /// True if the map view should show zoom controls. This includes two buttons 88 | /// to zoom in and zoom out. The default value is to show zoom controls. 89 | /// 90 | /// This is only supported on Android. And this field is silently ignored on iOS. 91 | final bool zoomControlsEnabled; 92 | 93 | /// True if the map view should respond to zoom gestures. 94 | final bool zoomGesturesEnabled; 95 | 96 | /// True if the map view should respond to tilt gestures. 97 | final bool tiltGesturesEnabled; 98 | 99 | /// Padding to be set on map. See https://developers.google.com/maps/documentation/android-sdk/map#map_padding for more details. 100 | final EdgeInsets padding; 101 | 102 | /// Markers to be placed on the map. 103 | final Set markers; 104 | 105 | /// Polygons to be placed on the map. 106 | final Set polygons; 107 | 108 | /// Polylines to be placed on the map. 109 | final Set polylines; 110 | 111 | /// Circles to be placed on the map. 112 | final Set circles; 113 | 114 | /// Called when the camera starts moving. 115 | /// 116 | /// This can be initiated by the following: 117 | /// 1. Non-gesture animation initiated in response to user actions. 118 | /// For example: zoom buttons, my location button, or marker clicks. 119 | /// 2. Programmatically initiated animation. 120 | /// 3. Camera motion initiated in response to user gestures on the map. 121 | /// For example: pan, tilt, pinch to zoom, or rotate. 122 | final VoidCallback? onCameraMoveStarted; 123 | 124 | /// Called repeatedly as the camera continues to move after an 125 | /// onCameraMoveStarted call. 126 | /// 127 | /// This may be called as often as once every frame and should 128 | /// not perform expensive operations. 129 | final CameraPositionCallback? onCameraMove; 130 | 131 | /// Called when camera movement has ended, there are no pending 132 | /// animations and the user has stopped interacting with the map. 133 | final VoidCallback? onCameraIdle; 134 | 135 | /// Called every time a [GoogleMap] is tapped. 136 | final ArgumentCallback? onTap; 137 | 138 | /// Called every time a [GoogleMap] is long pressed. 139 | final ArgumentCallback? onLongPress; 140 | 141 | /// True if a "My Location" layer should be shown on the map. 142 | /// 143 | /// This layer includes a location indicator at the current device location, 144 | /// as well as a My Location button. 145 | /// * The indicator is a small blue dot if the device is stationary, or a 146 | /// chevron if the device is moving. 147 | /// * The My Location button animates to focus on the user's current location 148 | /// if the user's location is currently known. 149 | /// 150 | /// Enabling this feature requires adding location permissions to both native 151 | /// platforms of your app. 152 | /// * On Android add either 153 | /// `` 154 | /// or `` 155 | /// to your `AndroidManifest.xml` file. `ACCESS_COARSE_LOCATION` returns a 156 | /// location with an accuracy approximately equivalent to a city block, while 157 | /// `ACCESS_FINE_LOCATION` returns as precise a location as possible, although 158 | /// it consumes more battery power. You will also need to request these 159 | /// permissions during run-time. If they are not granted, the My Location 160 | /// feature will fail silently. 161 | /// * On iOS add a `NSLocationWhenInUseUsageDescription` key to your 162 | /// `Info.plist` file. This will automatically prompt the user for permissions 163 | /// when the map tries to turn on the My Location layer. 164 | final bool myLocationEnabled; 165 | 166 | /// Enables or disables the my-location button. 167 | /// 168 | /// The my-location button causes the camera to move such that the user's 169 | /// location is in the center of the map. If the button is enabled, it is 170 | /// only shown when the my-location layer is enabled. 171 | /// 172 | /// By default, the my-location button is enabled (and hence shown when the 173 | /// my-location layer is enabled). 174 | /// 175 | /// See also: 176 | /// * [myLocationEnabled] parameter. 177 | final bool myLocationButtonEnabled; 178 | 179 | /// Enables or disables the traffic layer of the map 180 | final bool trafficEnabled; 181 | 182 | /// Which gestures should be consumed by the map. 183 | /// 184 | /// It is possible for other gesture recognizers to be competing with the map on pointer 185 | /// events, e.g if the map is inside a [ListView] the [ListView] will want to handle 186 | /// vertical drags. The map will claim gestures that are recognized by any of the 187 | /// recognizers on this list. 188 | /// 189 | /// When this set is empty, the map will only handle pointer events for gestures that 190 | /// were not claimed by any other gesture recognizer. 191 | final Set> gestureRecognizers; 192 | 193 | final PlatformMapsPlatformWidget _platform; 194 | 195 | @override 196 | Widget build(BuildContext context) { 197 | return _platform.build(context); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/platform_maps_platform.dart: -------------------------------------------------------------------------------- 1 | import 'package:platform_maps_flutter_platform_interface/src/platform_bitmap_descriptor.dart'; 2 | import 'package:platform_maps_flutter_platform_interface/src/platform_camera_update.dart'; 3 | import 'package:platform_maps_flutter_platform_interface/src/platform_maps_platform_widget.dart'; 4 | import 'package:platform_maps_flutter_platform_interface/src/types.dart'; 5 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 6 | 7 | /// Interface for a platform implementation of a PlatformMaps. 8 | abstract class PlatformMapsPlatform extends PlatformInterface { 9 | /// Creates a new [PlatformMapsPlatform]. 10 | PlatformMapsPlatform() : super(token: _token); 11 | 12 | static final Object _token = Object(); 13 | 14 | static PlatformMapsPlatform? _instance; 15 | 16 | /// The instance of [PlatformMapsPlatform] to use. 17 | static PlatformMapsPlatform? get instance => _instance; 18 | 19 | /// Platform-specific plugins should set this with their own platform-specific 20 | /// class that extends [PlatformMapsPlatform] when they register themselves. 21 | static set instance(PlatformMapsPlatform? instance) { 22 | if (instance == null) { 23 | throw AssertionError( 24 | 'Platform interfaces can only be set to a non-null instance', 25 | ); 26 | } 27 | 28 | PlatformInterface.verify(instance, _token); 29 | _instance = instance; 30 | } 31 | 32 | /// Create a new [PlatformPlatformMapsWidget]. 33 | /// 34 | /// This function should only be called by the app-facing package. 35 | /// Look at using [PlatformMap] in `platform_maps_flutter` instead. 36 | PlatformMapsPlatformWidget createPlatformMapsPlatformWidget( 37 | PlatformMapsPlatformWidgetCreationParams params, 38 | ) { 39 | throw UnimplementedError( 40 | 'createPlatformMapsPlatformWidget is not implemented on the current platform.', 41 | ); 42 | } 43 | 44 | /// Create a new [PlatformBitmapDescriptor]. 45 | /// This function should only be called by the app-facing package. 46 | PlatformBitmapDescriptor createBitmapDescriptor() { 47 | throw UnimplementedError( 48 | 'createBitmapDescriptor is not implemented on the current platform.', 49 | ); 50 | } 51 | 52 | PlatformCameraUpdate createPlatformCameraUpdate() { 53 | throw UnimplementedError( 54 | 'createCameraUpdate is not implemented on the current platform.', 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/platform_maps_platform_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 3 | 4 | abstract class PlatformMapsPlatformController { 5 | Future showMarkerInfoWindow(MarkerId markerId); 6 | Future hideMarkerInfoWindow(MarkerId markerId); 7 | Future isMarkerInfoWindowShown(MarkerId markerId); 8 | Future animateCamera(CameraUpdate cameraUpdate); 9 | Future moveCamera(CameraUpdate cameraUpdate); 10 | Future getVisibleRegion(); 11 | Future takeSnapshot(); 12 | } 13 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/platform_maps_platform_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:platform_maps_flutter_platform_interface/src/platform_maps_platform.dart'; 3 | import 'package:platform_maps_flutter_platform_interface/src/types.dart'; 4 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 5 | 6 | abstract class PlatformMapsPlatformWidget extends PlatformInterface { 7 | /// Creates a new [PlatformMapsPlatformWidget] 8 | factory PlatformMapsPlatformWidget( 9 | PlatformMapsPlatformWidgetCreationParams params, 10 | ) { 11 | assert( 12 | PlatformMapsPlatform.instance != null, 13 | 'A platform implementation for `platform_maps_flutter` has not been set. Please ' 14 | 'ensure that an implementation of `PlatformMapsPlatform` has been set to ' 15 | '`PlatformMapsPlatform.instance` before use. For unit testing, ' 16 | '`PlatformMapsPlatform.instance` can be set with your own test implementation.', 17 | ); 18 | final PlatformMapsPlatformWidget platformWidgetDelegate = 19 | PlatformMapsPlatform.instance!.createPlatformMapsPlatformWidget(params); 20 | PlatformInterface.verify(platformWidgetDelegate, _token); 21 | return platformWidgetDelegate; 22 | } 23 | 24 | /// Used by the platform implementation to create a new 25 | /// [PlatformMapsPlatformWidget]. 26 | /// 27 | /// Should only be used by platform implementations because they can't extend 28 | /// a class that only contains a factory constructor. 29 | @protected 30 | PlatformMapsPlatformWidget.implementation(this.params) : super(token: _token); 31 | 32 | static final Object _token = Object(); 33 | 34 | /// The parameters used to initialize the [PlatformMapsPlatformWidget]. 35 | final PlatformMapsPlatformWidgetCreationParams params; 36 | 37 | /// Builds a new WebView. 38 | /// 39 | /// Returns a Widget tree that embeds the created web view. 40 | Widget build(BuildContext context); 41 | } 42 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types.dart: -------------------------------------------------------------------------------- 1 | export 'types/bitmap.dart'; 2 | export 'types/callbacks.dart'; 3 | export 'types/camera_position.dart'; 4 | export 'types/camera_update.dart'; 5 | export 'types/cap.dart'; 6 | export 'types/circle.dart'; 7 | export 'types/controller.dart'; 8 | export 'types/info_window.dart'; 9 | export 'types/joint_type.dart'; 10 | export 'types/lat_lng.dart'; 11 | export 'types/map_type.dart'; 12 | export 'types/marker.dart'; 13 | export 'types/min_max_zoom_preference.dart'; 14 | export 'types/platform_maps_platform_widget_creation_params.dart'; 15 | export 'types/pattern_item.dart'; 16 | export 'types/polygon.dart'; 17 | export 'types/polyline.dart'; 18 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/bitmap.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter/widgets.dart'; 4 | import 'package:platform_maps_flutter_platform_interface/src/platform_bitmap_descriptor.dart'; 5 | 6 | /// Defines a bitmap image. For a marker, this class can be used to set the 7 | /// image of the marker icon. For a ground overlay, it can be used to set the 8 | /// image to place on the surface of the earth. 9 | 10 | abstract class BitmapDescriptor { 11 | /// Creates a [BitmapDescriptor] from an asset image. 12 | /// Asset images in flutter are stored per: https://flutter.dev/docs/development/ui/assets-and-images#declaring-resolution-aware-image-assets 13 | /// 14 | /// This method takes into consideration various asset resolutions and scales the images to the right resolution depending on the dpi. 15 | /// 16 | /// Don't forget to rebuild the map with the new Icons if it was already build. 17 | static Future fromAssetImage( 18 | ImageConfiguration configuration, 19 | String assetName, { 20 | AssetBundle? bundle, 21 | String? package, 22 | }) async { 23 | return PlatformBitmapDescriptor().fromAssetImage( 24 | configuration, 25 | assetName, 26 | bundle: bundle, 27 | package: package, 28 | ); 29 | } 30 | 31 | /// Creates a BitmapDescriptor using an array of bytes that must be encoded 32 | /// as PNG. 33 | static BitmapDescriptor fromBytes(Uint8List byteData) { 34 | return PlatformBitmapDescriptor().fromBytes(byteData); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/callbacks.dart: -------------------------------------------------------------------------------- 1 | /// Callback function taking a single argument. 2 | typedef ArgumentCallback = void Function(T argument); 3 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/camera_position.dart: -------------------------------------------------------------------------------- 1 | import 'package:platform_maps_flutter_platform_interface/src/types.dart'; 2 | 3 | /// The position of the map "camera", the view point from which the world is 4 | /// shown in the map view. Aggregates the camera's [target] geographical 5 | /// location, its [zoom] level, [pitch] angle, and [heading]. 6 | class CameraPosition { 7 | const CameraPosition({ 8 | required this.target, 9 | this.bearing = 0.0, 10 | this.tilt = 0.0, 11 | this.zoom = 0, 12 | }); 13 | 14 | /// The camera's bearing in degrees, measured clockwise from north. 15 | /// 16 | /// A bearing of 0.0, the default, means the camera points north. 17 | /// A bearing of 90.0 means the camera points east. 18 | final double bearing; 19 | 20 | /// The geographical location that the camera is pointing at. 21 | final LatLng target; 22 | 23 | // In degrees where 0 is looking straight down. Pitch may be clamped to an appropriate value. 24 | final double tilt; 25 | 26 | /// The zoom level of the camera. 27 | /// 28 | /// A zoom of 0.0, the default, means the screen width of the world is 256. 29 | /// Adding 1.0 to the zoom level doubles the screen width of the map. So at 30 | /// zoom level 3.0, the screen width of the world is 2³x256=2048. 31 | /// 32 | /// Larger zoom levels thus means the camera is placed closer to the surface 33 | /// of the Earth, revealing more detail in a narrower geographical region. 34 | /// 35 | /// The supported zoom level range depends on the map data and device. Values 36 | /// beyond the supported range are allowed, but on applying them to a map they 37 | /// will be silently clamped to the supported range. 38 | final double zoom; 39 | } 40 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/camera_update.dart: -------------------------------------------------------------------------------- 1 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 2 | 3 | abstract class CameraUpdate { 4 | const CameraUpdate(); 5 | 6 | /// Returns a camera update that moves the camera to the specified position. 7 | static CameraUpdate newCameraPosition(CameraPosition cameraPosition) => 8 | PlatformCameraUpdate().newCameraPosition(cameraPosition); 9 | 10 | /// Returns a camera update that moves the camera target to the specified geographical location. 11 | static CameraUpdate newLatLng(LatLng latLng) => 12 | PlatformCameraUpdate().newLatLng(latLng); 13 | 14 | /// Returns a camera update that moves the camera target to the specified geographical location and zoom level. 15 | static CameraUpdate newLatLngZoom(LatLng latLng, double zoom) => 16 | PlatformCameraUpdate().newLatLngZoom(latLng, zoom); 17 | 18 | /// Returns a camera update that transforms the camera so that 19 | /// the specified geographical bounding box is centered in the map 20 | /// view at the greatest possible zoom level. 21 | /// A non-zero [padding] insets the bounding box from the map view's edges. 22 | /// The camera's new tilt and bearing will both be 0.0. 23 | static CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) => 24 | PlatformCameraUpdate().newLatLngBounds(bounds, padding); 25 | 26 | /// Returns a camera update that modifies the camera zoom level by the specified amount. 27 | /// The optional [focus] is a screen point whose underlying geographical location 28 | /// should be invariant, if possible, by the movement. 29 | static CameraUpdate zoomBy(double amount) => 30 | PlatformCameraUpdate().zoomBy(amount); 31 | 32 | /// Returns a camera update that zooms the camera in, 33 | /// bringing the camera closer to the surface of the Earth. 34 | /// 35 | /// Equivalent to the result of calling zoomBy(1.0). 36 | static CameraUpdate zoomIn() => PlatformCameraUpdate().zoomIn(); 37 | 38 | /// Returns a camera update that zooms the camera out, 39 | /// bringing the camera further away from the surface of the Earth. 40 | /// 41 | /// Equivalent to the result of calling zoomBy(-1.0). 42 | static CameraUpdate zoomOut() => PlatformCameraUpdate().zoomOut(); 43 | 44 | /// Returns a camera update that sets the camera zoom level. 45 | static CameraUpdate zoomTo(double zoom) => 46 | PlatformCameraUpdate().zoomTo(zoom); 47 | } 48 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/cap.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Chromium Authors. All rights reserved. 2 | 3 | enum Cap { 4 | /// Cap that is squared off exactly at the start or end vertex of a [Polyline] with solid stroke pattern, 5 | /// equivalent to having no additional cap beyond the start or end vertex. 6 | /// 7 | /// This is the default cap type at start and end vertices of Polylines with solid stroke pattern. 8 | buttCap, 9 | 10 | /// Cap that is a semicircle with radius equal to half the stroke width, centered at 11 | /// the start or end vertex of a [Polyline] with solid stroke pattern. 12 | roundCap, 13 | 14 | /// Cap that is squared off after extending half the stroke width beyond the start 15 | /// or end vertex of a [Polyline] with solid stroke pattern. 16 | squareCap, 17 | } 18 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/circle.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'package:flutter/material.dart'; 6 | import 'package:platform_maps_flutter_platform_interface/src/types.dart'; 7 | 8 | /// Uniquely identifies a [Circle] among [PlatformMap] circles. 9 | /// 10 | /// This does not have to be globally unique, only unique among the list. 11 | @immutable 12 | class CircleId { 13 | /// Creates an immutable identifier for a [Circle]. 14 | const CircleId(this.value); 15 | 16 | /// value of the [CircleId]. 17 | final String value; 18 | 19 | @override 20 | bool operator ==(Object other) { 21 | if (identical(this, other)) return true; 22 | if (other is! CircleId) return false; 23 | final CircleId typedOther = other; 24 | return value == typedOther.value; 25 | } 26 | 27 | @override 28 | int get hashCode => value.hashCode; 29 | 30 | @override 31 | String toString() { 32 | return 'CircleId{value: $value}'; 33 | } 34 | } 35 | 36 | /// Draws a circle on the map. 37 | @immutable 38 | class Circle { 39 | /// Creates an immutable representation of a [Circle] to draw on [PlatformMap]. 40 | const Circle({ 41 | required this.circleId, 42 | this.consumeTapEvents = false, 43 | this.fillColor = Colors.transparent, 44 | this.center = const LatLng(0.0, 0.0), 45 | this.radius = 0, 46 | this.strokeColor = Colors.black, 47 | this.strokeWidth = 10, 48 | this.visible = true, 49 | this.onTap, 50 | }); 51 | 52 | /// Uniquely identifies a [Circle]. 53 | final CircleId circleId; 54 | 55 | /// True if the [Circle] consumes tap events. 56 | /// 57 | /// If this is false, [onTap] callback will not be triggered. 58 | final bool consumeTapEvents; 59 | 60 | /// Fill color in ARGB format, the same format used by Color. The default value is transparent (0x00000000). 61 | final Color fillColor; 62 | 63 | /// Geographical location of the circle center. 64 | final LatLng center; 65 | 66 | /// Radius of the circle in meters; must be positive. The default value is 0. 67 | final double radius; 68 | 69 | /// Fill color in ARGB format, the same format used by Color. The default value is black (0xff000000). 70 | final Color strokeColor; 71 | 72 | /// The width of the circle's outline in screen points. 73 | /// 74 | /// The width is constant and independent of the camera's zoom level. 75 | /// The default value is 10. 76 | /// Setting strokeWidth to 0 results in no stroke. 77 | final int strokeWidth; 78 | 79 | /// True if the circle is visible. 80 | final bool visible; 81 | 82 | /// Callbacks to receive tap events for circle placed on this map. 83 | final VoidCallback? onTap; 84 | 85 | /// Creates a new [Circle] object whose values are the same as this instance, 86 | /// unless overwritten by the specified parameters. 87 | Circle copyWith({ 88 | bool? consumeTapEventsParam, 89 | Color? fillColorParam, 90 | LatLng? centerParam, 91 | double? radiusParam, 92 | Color? strokeColorParam, 93 | int? strokeWidthParam, 94 | bool? visibleParam, 95 | VoidCallback? onTapParam, 96 | }) { 97 | return Circle( 98 | circleId: circleId, 99 | consumeTapEvents: consumeTapEventsParam ?? consumeTapEvents, 100 | fillColor: fillColorParam ?? fillColor, 101 | center: centerParam ?? center, 102 | radius: radiusParam ?? radius, 103 | strokeColor: strokeColorParam ?? strokeColor, 104 | strokeWidth: strokeWidthParam ?? strokeWidth, 105 | visible: visibleParam ?? visible, 106 | onTap: onTapParam ?? onTap, 107 | ); 108 | } 109 | 110 | /// Creates a new [Circle] object whose values are the same as this instance. 111 | Circle clone() => copyWith(); 112 | 113 | @override 114 | bool operator ==(Object other) { 115 | if (identical(this, other)) return true; 116 | if (other is! Circle) return false; 117 | final Circle typedOther = other; 118 | return circleId == typedOther.circleId && 119 | consumeTapEvents == typedOther.consumeTapEvents && 120 | fillColor == typedOther.fillColor && 121 | center == typedOther.center && 122 | radius == typedOther.radius && 123 | strokeColor == typedOther.strokeColor && 124 | strokeWidth == typedOther.strokeWidth && 125 | visible == typedOther.visible && 126 | onTap == typedOther.onTap; 127 | } 128 | 129 | @override 130 | int get hashCode => circleId.hashCode; 131 | } 132 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 4 | 5 | class PlatformMapController { 6 | final PlatformMapsPlatformController platformController; 7 | 8 | PlatformMapController(this.platformController); 9 | 10 | /// Programmatically show the Info Window for a [Marker]. 11 | /// 12 | /// The `markerId` must match one of the markers on the map. 13 | /// An invalid `markerId` triggers an "Invalid markerId" error. 14 | /// 15 | /// * See also: 16 | /// * [hideMarkerInfoWindow] to hide the Info Window. 17 | /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. 18 | Future showMarkerInfoWindow(MarkerId markerId) => 19 | platformController.showMarkerInfoWindow(markerId); 20 | 21 | /// Programmatically hide the Info Window for a [Marker]. 22 | /// 23 | /// The `markerId` must match one of the markers on the map. 24 | /// An invalid `markerId` triggers an "Invalid markerId" error. 25 | /// 26 | /// * See also: 27 | /// * [showMarkerInfoWindow] to show the Info Window. 28 | /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. 29 | Future hideMarkerInfoWindow(MarkerId markerId) => 30 | platformController.hideMarkerInfoWindow(markerId); 31 | 32 | /// Returns `true` when the [InfoWindow] is showing, `false` otherwise. 33 | /// 34 | /// The `markerId` must match one of the markers on the map. 35 | /// An invalid `markerId` triggers an "Invalid markerId" error. 36 | /// 37 | /// * See also: 38 | /// * [showMarkerInfoWindow] to show the Info Window. 39 | /// * [hideMarkerInfoWindow] to hide the Info Window. 40 | Future isMarkerInfoWindowShown(MarkerId markerId) => 41 | platformController.isMarkerInfoWindowShown(markerId); 42 | 43 | /// Starts an animated change of the map camera position. 44 | /// 45 | /// The returned [Future] completes after the change has been started on the 46 | /// platform side. 47 | Future animateCamera(cameraUpdate) => 48 | platformController.animateCamera(cameraUpdate); 49 | 50 | /// Changes the map camera position. 51 | /// 52 | /// The returned [Future] completes after the change has been made on the 53 | /// platform side. 54 | Future moveCamera(cameraUpdate) => 55 | platformController.moveCamera(cameraUpdate); 56 | 57 | /// Return [LatLngBounds] defining the region that is visible in a map. 58 | Future getVisibleRegion() => 59 | platformController.getVisibleRegion(); 60 | 61 | /// Returns the image bytes of the map 62 | Future takeSnapshot() => platformController.takeSnapshot(); 63 | } 64 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/info_window.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | /// Text labels for a [Marker] info window. 4 | class InfoWindow { 5 | const InfoWindow({this.title, this.snippet, this.onTap, this.anchor}); 6 | 7 | /// Text labels specifying that no text is to be displayed. 8 | static const InfoWindow noText = InfoWindow(); 9 | 10 | /// Text displayed in an info window when the user taps the marker. 11 | /// 12 | /// A null value means no title. 13 | final String? title; 14 | 15 | /// Additional text displayed below the [title]. 16 | /// 17 | /// A null value means no additional text. 18 | final String? snippet; 19 | 20 | /// The icon image point that will be the anchor of the info window when 21 | /// displayed. 22 | /// 23 | /// The image point is specified in normalized coordinates: An anchor of 24 | /// (0.0, 0.0) means the top left corner of the image. An anchor 25 | /// of (1.0, 1.0) means the bottom right corner of the image. 26 | final Offset? anchor; 27 | 28 | /// onTap callback for this [InfoWindow]. 29 | final VoidCallback? onTap; 30 | 31 | /// Creates a new [InfoWindow] object whose values are the same as this instance, 32 | /// unless overwritten by the specified parameters. 33 | InfoWindow copyWith({ 34 | String? titleParam, 35 | String? snippetParam, 36 | Offset? anchorParam, 37 | VoidCallback? onTapParam, 38 | }) { 39 | return InfoWindow( 40 | title: titleParam ?? title, 41 | snippet: snippetParam ?? snippet, 42 | anchor: anchorParam ?? anchor, 43 | onTap: onTapParam ?? onTap, 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/joint_type.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'package:flutter/widgets.dart'; 6 | 7 | /// Joint types for [Polyline]. 8 | @immutable 9 | class JointType { 10 | const JointType._(this.value); 11 | 12 | /// The value representing the [JointType] on the sdk. 13 | final int value; 14 | 15 | /// Mitered joint, with fixed pointed extrusion equal to half the stroke width on the outside of the joint. 16 | /// 17 | /// Constant Value: 0 18 | static const JointType mitered = JointType._(0); 19 | 20 | /// Flat bevel on the outside of the joint. 21 | /// 22 | /// Constant Value: 1 23 | static const JointType bevel = JointType._(1); 24 | 25 | /// Rounded on the outside of the joint by an arc of radius equal to half the stroke width, centered at the vertex. 26 | /// 27 | /// Constant Value: 2 28 | static const JointType round = JointType._(2); 29 | } 30 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/lat_lng.dart: -------------------------------------------------------------------------------- 1 | /// A pair of latitude and longitude coordinates, stored as degrees. 2 | class LatLng { 3 | /// Creates a geographical location specified in degrees [latitude] and 4 | /// [longitude]. 5 | /// 6 | /// The latitude is clamped to the inclusive interval from -90.0 to +90.0. 7 | /// 8 | /// The longitude is normalized to the half-open interval from -180.0 9 | /// (inclusive) to +180.0 (exclusive) 10 | const LatLng(double latitude, double longitude) 11 | : latitude = 12 | (latitude < -90.0 ? -90.0 : (90.0 < latitude ? 90.0 : latitude)), 13 | longitude = (longitude + 180.0) % 360.0 - 180.0; 14 | 15 | /// The latitude in degrees between -90.0 and 90.0, both inclusive. 16 | final double latitude; 17 | 18 | /// The longitude in degrees between -180.0 (inclusive) and 180.0 (exclusive). 19 | final double longitude; 20 | 21 | @override 22 | String toString() => '$runtimeType($latitude, $longitude)'; 23 | } 24 | 25 | class LatLngBounds { 26 | /// Creates geographical bounding box with the specified corners. 27 | /// 28 | /// The latitude of the southwest corner cannot be larger than the 29 | /// latitude of the northeast corner. 30 | LatLngBounds({required this.southwest, required this.northeast}) 31 | : assert(southwest.latitude <= northeast.latitude); 32 | 33 | /// The southwest corner of the rectangle. 34 | final LatLng southwest; 35 | 36 | /// The northeast corner of the rectangle. 37 | final LatLng northeast; 38 | 39 | bool contains(LatLng point) { 40 | return _containsLatitude(point.latitude) && 41 | _containsLongitude(point.longitude); 42 | } 43 | 44 | bool _containsLatitude(double lat) { 45 | return (southwest.latitude <= lat) && (lat <= northeast.latitude); 46 | } 47 | 48 | bool _containsLongitude(double lng) { 49 | if (southwest.longitude <= northeast.longitude) { 50 | return southwest.longitude <= lng && lng <= northeast.longitude; 51 | } else { 52 | return southwest.longitude <= lng || lng <= northeast.longitude; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/map_type.dart: -------------------------------------------------------------------------------- 1 | /// Type of map tiles to display. 2 | enum MapType { 3 | /// Normal tiles (traffic and labels, subtle terrain information). 4 | normal, 5 | 6 | /// Satellite imaging tiles (aerial photos) 7 | satellite, 8 | 9 | /// Hybrid tiles (satellite images with some labels/overlays) 10 | hybrid, 11 | } 12 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/marker.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 3 | 4 | /// Uniquely identifies a [Marker] among [PlatformMaps] markers. 5 | /// 6 | /// This does not have to be globally unique, only unique among the list. 7 | @immutable 8 | class MarkerId { 9 | const MarkerId(this.value); 10 | 11 | /// value of the [MarkerId]. 12 | final String value; 13 | } 14 | 15 | /// Marks a geographical location on the map. 16 | /// 17 | /// A marker icon is drawn oriented against the device's screen rather than 18 | /// the map's surface; that is, it will not necessarily change orientation 19 | /// due to map rotations, tilting, or zooming. 20 | @immutable 21 | class Marker { 22 | /// Creates a set of marker configuration options. 23 | /// 24 | /// Default marker options. 25 | /// 26 | /// Specifies a marker that 27 | /// * is fully opaque; [alpha] is 1.0 28 | /// * has default tap handling; [consumeTapEvents] is false 29 | /// * is stationary; [draggable] is false 30 | /// * has a default icon; [icon] is `BitmapDescriptor.defaultMarker` 31 | /// * has no info window text; [infoWindowText] is `InfoWindowText.noText` 32 | /// * is positioned at 0, 0; [position] is `LatLng(0.0, 0.0)` 33 | /// * is visible; [visible] is true 34 | /// * is placed at the base of the drawing order; [zIndex] is 0.0 35 | const Marker({ 36 | required this.markerId, 37 | this.alpha = 1.0, 38 | this.anchor = const Offset(0.5, 1.0), 39 | this.consumeTapEvents = false, 40 | this.draggable = false, 41 | this.icon, 42 | this.infoWindow = InfoWindow.noText, 43 | this.position = const LatLng(0.0, 0.0), 44 | this.onTap, 45 | this.visible = true, 46 | this.onDragEnd, 47 | }) : assert((0.0 <= alpha && alpha <= 1.0)); 48 | 49 | /// Uniquely identifies a [Marker]. 50 | final MarkerId markerId; 51 | 52 | /// The opacity of the marker, between 0.0 and 1.0 inclusive. 53 | /// 54 | /// 0.0 means fully transparent, 1.0 means fully opaque. 55 | final double alpha; 56 | 57 | /// The icon image point that will be placed at the [position] of the marker. 58 | /// 59 | /// The image point is specified in normalized coordinates: An anchor of 60 | /// (0.0, 0.0) means the top left corner of the image. An anchor 61 | /// of (1.0, 1.0) means the bottom right corner of the image. 62 | final Offset anchor; 63 | 64 | /// True if the marker icon consumes tap events. If not, the map will perform 65 | /// default tap handling by centering the map on the marker and displaying its 66 | /// info window. 67 | final bool consumeTapEvents; 68 | 69 | /// True if the marker is draggable by user touch events. 70 | final bool draggable; 71 | 72 | /// A description of the bitmap used to draw the marker icon. 73 | final BitmapDescriptor? icon; 74 | 75 | /// A Google Maps InfoWindow. 76 | /// 77 | /// The window is displayed when the marker is tapped. 78 | final InfoWindow infoWindow; 79 | 80 | /// Geographical location of the marker. 81 | final LatLng position; 82 | 83 | /// Callbacks to receive tap events for markers placed on this map. 84 | final VoidCallback? onTap; 85 | 86 | /// True if the annotation is visible. 87 | final bool visible; 88 | 89 | final ValueChanged? onDragEnd; 90 | 91 | Marker copyWith({ 92 | double? alphaParam, 93 | Offset? anchorParam, 94 | bool? consumeTapEventsParam, 95 | bool? draggableParam, 96 | BitmapDescriptor? iconParam, 97 | InfoWindow? infoWindowParam, 98 | LatLng? positionParam, 99 | bool? visibleParam, 100 | VoidCallback? onTapParam, 101 | }) { 102 | return Marker( 103 | markerId: markerId, 104 | alpha: alphaParam ?? alpha, 105 | anchor: anchorParam ?? anchor, 106 | consumeTapEvents: consumeTapEventsParam ?? consumeTapEvents, 107 | draggable: draggableParam ?? draggable, 108 | icon: iconParam ?? icon, 109 | infoWindow: infoWindowParam ?? infoWindow, 110 | position: positionParam ?? position, 111 | visible: visibleParam ?? visible, 112 | onTap: onTapParam ?? onTap, 113 | ); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/min_max_zoom_preference.dart: -------------------------------------------------------------------------------- 1 | /// Used with [PlatformMapOptions] to wrap min and max zoom. This allows 2 | /// distinguishing between specifying unbounded zooming (null `minZoom` and 3 | /// `maxZoom`) from not specifying anything (null `MinMaxZoomPreference`). 4 | class MinMaxZoomPreference { 5 | const MinMaxZoomPreference(this.minZoom, this.maxZoom) 6 | : assert(minZoom == null || maxZoom == null || minZoom <= maxZoom); 7 | 8 | static const unbounded = MinMaxZoomPreference(null, null); 9 | 10 | /// The preferred minimum zoom level or null, if unbounded from below. 11 | final double? minZoom; 12 | 13 | /// The preferred maximum zoom level or null, if unbounded from above. 14 | final double? maxZoom; 15 | 16 | /// Converts this object to something serializable in JSON. 17 | dynamic toJson() => [minZoom, maxZoom]; 18 | } 19 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/pattern_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Item used in the stroke pattern for a Polyline. 4 | @immutable 5 | sealed class PatternItem { 6 | const PatternItem._(); 7 | 8 | static const PatternItem dot = DotPatternItem(); 9 | 10 | /// A dash used in the stroke pattern for a [Polyline]. 11 | /// 12 | /// [length] has to be non-negative. 13 | static PatternItem dash(double length) { 14 | assert(length >= 0.0); 15 | return DashPatternItem(length); 16 | } 17 | 18 | /// A gap used in the stroke pattern for a [Polyline]. 19 | /// 20 | /// [length] has to be non-negative. 21 | static PatternItem gap(double length) { 22 | assert(length >= 0.0); 23 | return GapPatternItem(length); 24 | } 25 | } 26 | 27 | class DotPatternItem extends PatternItem { 28 | const DotPatternItem() : super._(); 29 | } 30 | 31 | class DashPatternItem extends PatternItem { 32 | final double length; 33 | const DashPatternItem(this.length) : super._(); 34 | } 35 | 36 | class GapPatternItem extends PatternItem { 37 | final double length; 38 | const GapPatternItem(this.length) : super._(); 39 | } 40 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/platform_maps_platform_widget_creation_params.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/gestures.dart'; 3 | import 'package:flutter/widgets.dart'; 4 | 5 | import 'package:platform_maps_flutter_platform_interface/src/types.dart'; 6 | 7 | typedef MapCreatedCallback = void Function(PlatformMapController controller); 8 | 9 | typedef CameraPositionCallback = void Function(CameraPosition position); 10 | 11 | class PlatformMapsPlatformWidgetCreationParams { 12 | const PlatformMapsPlatformWidgetCreationParams({ 13 | Key? key, 14 | required this.initialCameraPosition, 15 | this.onMapCreated, 16 | this.gestureRecognizers = const >{}, 17 | this.compassEnabled = true, 18 | this.mapType = MapType.normal, 19 | this.minMaxZoomPreference = MinMaxZoomPreference.unbounded, 20 | this.rotateGesturesEnabled = true, 21 | this.scrollGesturesEnabled = true, 22 | this.zoomControlsEnabled = true, 23 | this.zoomGesturesEnabled = true, 24 | this.tiltGesturesEnabled = true, 25 | this.myLocationEnabled = false, 26 | this.myLocationButtonEnabled = false, 27 | this.padding = const EdgeInsets.all(0), 28 | this.trafficEnabled = false, 29 | this.markers = const {}, 30 | this.polygons = const {}, 31 | this.polylines = const {}, 32 | this.circles = const {}, 33 | this.onCameraMoveStarted, 34 | this.onCameraMove, 35 | this.onCameraIdle, 36 | this.onTap, 37 | this.onLongPress, 38 | }); 39 | 40 | /// Callback method for when the map is ready to be used. 41 | /// 42 | /// Used to receive a [GoogleMapController] for this [GoogleMap]. 43 | final MapCreatedCallback? onMapCreated; 44 | 45 | /// The initial position of the map's camera. 46 | final CameraPosition initialCameraPosition; 47 | 48 | /// True if the map should show a compass when rotated. 49 | final bool compassEnabled; 50 | 51 | /// Type of map tiles to be rendered. 52 | final MapType mapType; 53 | 54 | /// Preferred bounds for the camera zoom level. 55 | /// 56 | /// Actual bounds depend on map data and device. 57 | final MinMaxZoomPreference minMaxZoomPreference; 58 | 59 | /// True if the map view should respond to rotate gestures. 60 | final bool rotateGesturesEnabled; 61 | 62 | /// True if the map view should respond to scroll gestures. 63 | final bool scrollGesturesEnabled; 64 | 65 | /// True if the map view should show zoom controls. This includes two buttons 66 | /// to zoom in and zoom out. The default value is to show zoom controls. 67 | /// 68 | /// This is only supported on Android. And this field is silently ignored on iOS. 69 | final bool zoomControlsEnabled; 70 | 71 | /// True if the map view should respond to zoom gestures. 72 | final bool zoomGesturesEnabled; 73 | 74 | /// True if the map view should respond to tilt gestures. 75 | final bool tiltGesturesEnabled; 76 | 77 | /// Padding to be set on map. See https://developers.google.com/maps/documentation/android-sdk/map#map_padding for more details. 78 | final EdgeInsets padding; 79 | 80 | /// Markers to be placed on the map. 81 | final Set markers; 82 | 83 | /// Polygons to be placed on the map. 84 | final Set polygons; 85 | 86 | /// Polylines to be placed on the map. 87 | final Set polylines; 88 | 89 | /// Circles to be placed on the map. 90 | final Set circles; 91 | 92 | /// Called when the camera starts moving. 93 | /// 94 | /// This can be initiated by the following: 95 | /// 1. Non-gesture animation initiated in response to user actions. 96 | /// For example: zoom buttons, my location button, or marker clicks. 97 | /// 2. Programmatically initiated animation. 98 | /// 3. Camera motion initiated in response to user gestures on the map. 99 | /// For example: pan, tilt, pinch to zoom, or rotate. 100 | final VoidCallback? onCameraMoveStarted; 101 | 102 | /// Called repeatedly as the camera continues to move after an 103 | /// onCameraMoveStarted call. 104 | /// 105 | /// This may be called as often as once every frame and should 106 | /// not perform expensive operations. 107 | final CameraPositionCallback? onCameraMove; 108 | 109 | /// Called when camera movement has ended, there are no pending 110 | /// animations and the user has stopped interacting with the map. 111 | final VoidCallback? onCameraIdle; 112 | 113 | /// Called every time a [GoogleMap] is tapped. 114 | final ArgumentCallback? onTap; 115 | 116 | /// Called every time a [GoogleMap] is long pressed. 117 | final ArgumentCallback? onLongPress; 118 | 119 | /// True if a "My Location" layer should be shown on the map. 120 | /// 121 | /// This layer includes a location indicator at the current device location, 122 | /// as well as a My Location button. 123 | /// * The indicator is a small blue dot if the device is stationary, or a 124 | /// chevron if the device is moving. 125 | /// * The My Location button animates to focus on the user's current location 126 | /// if the user's location is currently known. 127 | /// 128 | /// Enabling this feature requires adding location permissions to both native 129 | /// platforms of your app. 130 | /// * On Android add either 131 | /// `` 132 | /// or `` 133 | /// to your `AndroidManifest.xml` file. `ACCESS_COARSE_LOCATION` returns a 134 | /// location with an accuracy approximately equivalent to a city block, while 135 | /// `ACCESS_FINE_LOCATION` returns as precise a location as possible, although 136 | /// it consumes more battery power. You will also need to request these 137 | /// permissions during run-time. If they are not granted, the My Location 138 | /// feature will fail silently. 139 | /// * On iOS add a `NSLocationWhenInUseUsageDescription` key to your 140 | /// `Info.plist` file. This will automatically prompt the user for permissions 141 | /// when the map tries to turn on the My Location layer. 142 | final bool myLocationEnabled; 143 | 144 | /// Enables or disables the my-location button. 145 | /// 146 | /// The my-location button causes the camera to move such that the user's 147 | /// location is in the center of the map. If the button is enabled, it is 148 | /// only shown when the my-location layer is enabled. 149 | /// 150 | /// By default, the my-location button is enabled (and hence shown when the 151 | /// my-location layer is enabled). 152 | /// 153 | /// See also: 154 | /// * [myLocationEnabled] parameter. 155 | final bool myLocationButtonEnabled; 156 | 157 | /// Enables or disables the traffic layer of the map 158 | final bool trafficEnabled; 159 | 160 | /// Which gestures should be consumed by the map. 161 | /// 162 | /// It is possible for other gesture recognizers to be competing with the map on pointer 163 | /// events, e.g if the map is inside a [ListView] the [ListView] will want to handle 164 | /// vertical drags. The map will claim gestures that are recognized by any of the 165 | /// recognizers on this list. 166 | /// 167 | /// When this set is empty, the map will only handle pointer events for gestures that 168 | /// were not claimed by any other gesture recognizer. 169 | final Set> gestureRecognizers; 170 | } 171 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/polygon.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'package:flutter/foundation.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:platform_maps_flutter_platform_interface/src/types.dart'; 8 | 9 | /// Uniquely identifies a [Polygon] among [PlatformMap] polygons. 10 | /// 11 | /// This does not have to be globally unique, only unique among the list. 12 | @immutable 13 | class PolygonId { 14 | /// Creates an immutable identifier for a [Polygon]. 15 | const PolygonId(this.value); 16 | 17 | /// value of the [PolygonId]. 18 | final String value; 19 | 20 | @override 21 | bool operator ==(Object other) { 22 | if (identical(this, other)) return true; 23 | if (other is! PolygonId) return false; 24 | final PolygonId typedOther = other; 25 | return value == typedOther.value; 26 | } 27 | 28 | @override 29 | int get hashCode => value.hashCode; 30 | 31 | @override 32 | String toString() { 33 | return 'PolygonId{value: $value}'; 34 | } 35 | } 36 | 37 | /// Draws a polygon through geographical locations on the map. 38 | @immutable 39 | class Polygon { 40 | /// Creates an immutable representation of a polygon through geographical locations on the map. 41 | const Polygon({ 42 | required this.polygonId, 43 | this.consumeTapEvents = false, 44 | this.fillColor = Colors.black, 45 | this.points = const [], 46 | this.strokeColor = Colors.black, 47 | this.strokeWidth = 10, 48 | this.visible = true, 49 | this.onTap, 50 | }); 51 | 52 | /// Uniquely identifies a [Polygon]. 53 | final PolygonId polygonId; 54 | 55 | /// True if the [Polygon] consumes tap events. 56 | /// 57 | /// If this is false, [onTap] callback will not be triggered. 58 | final bool consumeTapEvents; 59 | 60 | /// Fill color in ARGB format, the same format used by Color. The default value is black (0xff000000). 61 | final Color fillColor; 62 | 63 | /// The vertices of the polygon to be drawn. 64 | /// 65 | /// Line segments are drawn between consecutive points. A polygon is not closed by 66 | /// default; to form a closed polygon, the start and end points must be the same. 67 | final List points; 68 | 69 | /// True if the marker is visible. 70 | final bool visible; 71 | 72 | /// Line color in ARGB format, the same format used by Color. The default value is black (0xff000000). 73 | final Color strokeColor; 74 | 75 | /// Width of the polygon, used to define the width of the line to be drawn. 76 | /// 77 | /// The width is constant and independent of the camera's zoom level. 78 | /// The default value is 10. 79 | final int strokeWidth; 80 | 81 | /// Callbacks to receive tap events for polygon placed on this map. 82 | final VoidCallback? onTap; 83 | 84 | /// Creates a new [Polygon] object whose values are the same as this instance, 85 | /// unless overwritten by the specified parameters. 86 | Polygon copyWith({ 87 | bool? consumeTapEventsParam, 88 | List? pointsParam, 89 | Color? strokeColorParam, 90 | Color? fillColorParam, 91 | int? strokeWidthParam, 92 | bool? visibleParam, 93 | VoidCallback? onTapParam, 94 | }) { 95 | return Polygon( 96 | polygonId: polygonId, 97 | consumeTapEvents: consumeTapEventsParam ?? consumeTapEvents, 98 | points: pointsParam ?? points, 99 | strokeColor: strokeColorParam ?? strokeColor, 100 | fillColor: fillColorParam ?? fillColor, 101 | strokeWidth: strokeWidthParam ?? strokeWidth, 102 | visible: visibleParam ?? visible, 103 | onTap: onTapParam ?? onTap, 104 | ); 105 | } 106 | 107 | /// Creates a new [Polygon] object whose values are the same as this instance. 108 | Polygon clone() { 109 | return copyWith(pointsParam: List.of(points)); 110 | } 111 | 112 | @override 113 | bool operator ==(Object other) { 114 | if (identical(this, other)) return true; 115 | if (other is! Polygon) return false; 116 | final Polygon typedOther = other; 117 | return polygonId == typedOther.polygonId && 118 | consumeTapEvents == typedOther.consumeTapEvents && 119 | fillColor == typedOther.fillColor && 120 | listEquals(points, typedOther.points) && 121 | visible == typedOther.visible && 122 | strokeColor == typedOther.strokeColor && 123 | strokeWidth == typedOther.strokeWidth && 124 | onTap == typedOther.onTap; 125 | } 126 | 127 | @override 128 | int get hashCode => polygonId.hashCode; 129 | } 130 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/lib/src/types/polyline.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 3 | 4 | /// Uniquely identifies a [Polyline] among [AppleMap] polylines. 5 | /// 6 | /// This does not have to be globally unique, only unique among the list. 7 | @immutable 8 | class PolylineId { 9 | const PolylineId(this.value); 10 | 11 | /// value of the [PolylineId]. 12 | final String value; 13 | } 14 | 15 | /// Draws a line through geographical locations on the map. 16 | @immutable 17 | class Polyline { 18 | const Polyline({ 19 | required this.polylineId, 20 | this.consumeTapEvents = false, 21 | this.color = Colors.black, 22 | this.polylineCap = Cap.buttCap, 23 | this.jointType = JointType.mitered, 24 | this.points = const [], 25 | this.patterns = const [], 26 | this.visible = true, 27 | this.width = 10, 28 | this.zIndex = 0, 29 | this.onTap, 30 | }); 31 | 32 | /// Uniquely identifies a [Polyline]. 33 | final PolylineId polylineId; 34 | 35 | /// True if the [Polyline] consumes tap events. 36 | /// 37 | /// If this is false, [onTap] callback will not be triggered. 38 | final bool consumeTapEvents; 39 | 40 | /// Line segment color in ARGB format, the same format used by Color. The default value is black (0xff000000). 41 | final Color color; 42 | 43 | /// Indicates whether the segments of the polyline should be drawn as geodesics, as opposed to straight lines 44 | /// on the Mercator projection. 45 | /// 46 | /// A geodesic is the shortest path between two points on the Earth's surface. 47 | /// The geodesic curve is constructed assuming the Earth is a sphere 48 | // final bool geodesic; 49 | 50 | /// Joint type of the polyline line segments. 51 | /// 52 | /// The joint type defines the shape to be used when joining adjacent line segments at all vertices of the 53 | /// polyline except the start and end vertices. See [JointType] for supported joint types. The default value is 54 | /// mitered. 55 | /// 56 | /// Supported on Android only. 57 | final JointType jointType; 58 | 59 | /// The stroke pattern for the polyline. 60 | /// 61 | /// Solid or a sequence of PatternItem objects to be repeated along the line. 62 | /// Available PatternItem types: Gap (defined by gap length in pixels), Dash (defined by line width and dash 63 | /// length in pixels) and Dot (circular, centered on the line, diameter defined by line width in pixels). 64 | /// 65 | /// Note: It is not possible to have a mix of dots and dashes. 66 | final List patterns; 67 | 68 | /// The vertices of the polyline to be drawn. 69 | /// 70 | /// Line segments are drawn between consecutive points. A polyline is not closed by 71 | /// default; to form a closed polyline, the start and end points must be the same. 72 | final List points; 73 | 74 | /// The cap at the end vertex of the polyline. 75 | /// 76 | /// The default end cap is ButtCap. 77 | final Cap polylineCap; 78 | 79 | /// True if the marker is visible. 80 | final bool visible; 81 | 82 | /// Width of the polyline, used to define the width of the line segment to be drawn. 83 | /// 84 | /// The width is constant and independent of the camera's zoom level. 85 | /// The default value is 10. 86 | final int width; 87 | 88 | /// The z-index of the polyline, used to determine relative drawing order of 89 | /// map overlays. 90 | /// 91 | /// Overlays are drawn in order of z-index, so that lower values means drawn 92 | /// earlier, and thus appearing to be closer to the surface of the Earth. 93 | final int zIndex; 94 | 95 | /// Callbacks to receive tap events for polyline placed on this map. 96 | final VoidCallback? onTap; 97 | 98 | Polyline copyWith({ 99 | Color? colorParam, 100 | bool? consumeTapEventsParam, 101 | Cap? polylineCapParam, 102 | JointType? jointTypeParam, 103 | List? patternsParam, 104 | List? pointsParam, 105 | bool? visibleParam, 106 | int? widthParam, 107 | int? zIndexParam, 108 | VoidCallback? onTapParam, 109 | }) { 110 | return Polyline( 111 | polylineId: polylineId, 112 | color: colorParam ?? color, 113 | consumeTapEvents: consumeTapEventsParam ?? consumeTapEvents, 114 | polylineCap: polylineCapParam ?? polylineCap, 115 | jointType: jointTypeParam ?? jointType, 116 | patterns: patternsParam ?? patterns, 117 | points: pointsParam ?? points, 118 | visible: visibleParam ?? visible, 119 | width: widthParam ?? width, 120 | onTap: onTapParam ?? onTap, 121 | zIndex: zIndexParam ?? zIndex, 122 | ); 123 | } 124 | 125 | @override 126 | bool operator ==(Object other) { 127 | if (identical(this, other)) return true; 128 | if (other is! Polyline) return false; 129 | final Polyline typedOther = other; 130 | return polylineId == typedOther.polylineId; 131 | } 132 | 133 | @override 134 | int get hashCode => polylineId.hashCode; 135 | } 136 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: platform_maps_flutter_platform_interface 2 | description: platform interface for platform_maps_flutter package 3 | version: 1.0.0-beta.1 4 | homepage: https://github.com/albert-heijn-technology 5 | repository: https://github.com/albert-heijn-technology/platform_maps_flutter/tree/master/packages/platform_maps_flutter_platform_interface 6 | issue_tracker: https://github.com/albert-heijn-technology/platform_maps_flutter/issues 7 | # NOTE: We strongly prefer non-breaking changes, even at the expense of a 8 | # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes 9 | 10 | environment: 11 | sdk: ^3.2.4 12 | 13 | dependencies: 14 | flutter: 15 | sdk: flutter 16 | plugin_platform_interface: ^2.1.8 17 | 18 | dev_dependencies: 19 | flutter_lints: ^3.0.1 20 | flutter_test: 21 | sdk: flutter 22 | -------------------------------------------------------------------------------- /packages/platform_maps_flutter_platform_interface/test/platform_maps_flutter_platform_interface_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:platform_maps_flutter_platform_interface/platform_maps_flutter_platform_interface.dart'; 5 | import 'package:flutter_test/flutter_test.dart'; 6 | 7 | void main() { 8 | test('Verify widget generation', () { 9 | PlatformMapsPlatform.instance = FakePlatform(); 10 | 11 | final widget = PlatformMapsPlatformWidget( 12 | const PlatformMapsPlatformWidgetCreationParams( 13 | initialCameraPosition: CameraPosition(target: LatLng(0, 0)), 14 | ), 15 | ); 16 | expect(widget, isA()); 17 | }); 18 | 19 | test('Verify bitmap descriptor generation', () { 20 | PlatformMapsPlatform.instance = FakePlatform(); 21 | 22 | final platformBitmapDescriptor = PlatformBitmapDescriptor(); 23 | expect(platformBitmapDescriptor, isA()); 24 | 25 | final bitmapDescriptor = 26 | platformBitmapDescriptor.fromBytes(Uint8List.fromList([1, 2])); 27 | expect(bitmapDescriptor, isA()); 28 | }); 29 | 30 | test('Verify camera update generation', () { 31 | PlatformMapsPlatform.instance = FakePlatform(); 32 | 33 | final platformCameraUpdate = PlatformCameraUpdate(); 34 | expect(platformCameraUpdate, isA()); 35 | 36 | final cameraUpdate = platformCameraUpdate.zoomIn(); 37 | expect(cameraUpdate, isA()); 38 | }); 39 | } 40 | 41 | class FakePlatform extends PlatformMapsPlatform { 42 | @override 43 | PlatformMapsPlatformWidget createPlatformMapsPlatformWidget( 44 | PlatformMapsPlatformWidgetCreationParams params, 45 | ) { 46 | return FakeWidget(params); 47 | } 48 | 49 | @override 50 | PlatformBitmapDescriptor createBitmapDescriptor() => 51 | FakePlatformBitmapDescriptor(); 52 | 53 | @override 54 | PlatformCameraUpdate createPlatformCameraUpdate() => 55 | FakePlatformCameraUpdate(); 56 | } 57 | 58 | class FakeWidget extends PlatformMapsPlatformWidget { 59 | FakeWidget(super.params) : super.implementation(); 60 | 61 | @override 62 | Widget build(BuildContext context) { 63 | return const Placeholder(); 64 | } 65 | } 66 | 67 | class FakePlatformBitmapDescriptor extends PlatformBitmapDescriptor { 68 | FakePlatformBitmapDescriptor() : super.implementation(); 69 | 70 | @override 71 | Future fromAssetImage( 72 | ImageConfiguration configuration, 73 | String assetName, { 74 | AssetBundle? bundle, 75 | String? package, 76 | }) { 77 | return Future.value(FakeBitmapDescriptor()); 78 | } 79 | 80 | @override 81 | BitmapDescriptor fromBytes(Uint8List byteData) { 82 | return FakeBitmapDescriptor(); 83 | } 84 | } 85 | 86 | class FakeBitmapDescriptor extends BitmapDescriptor {} 87 | 88 | class FakePlatformCameraUpdate extends PlatformCameraUpdate { 89 | FakePlatformCameraUpdate() : super.implementation(); 90 | 91 | @override 92 | CameraUpdate zoomIn() => FakeCameraUpdate(); 93 | 94 | @override 95 | CameraUpdate newCameraPosition(CameraPosition cameraPosition) { 96 | throw UnimplementedError(); 97 | } 98 | 99 | @override 100 | CameraUpdate newLatLng(LatLng latLng) { 101 | throw UnimplementedError(); 102 | } 103 | 104 | @override 105 | CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) { 106 | throw UnimplementedError(); 107 | } 108 | 109 | @override 110 | CameraUpdate newLatLngZoom(LatLng latLng, double zoom) { 111 | throw UnimplementedError(); 112 | } 113 | 114 | @override 115 | CameraUpdate zoomBy(double amount) { 116 | throw UnimplementedError(); 117 | } 118 | 119 | @override 120 | CameraUpdate zoomOut() { 121 | throw UnimplementedError(); 122 | } 123 | 124 | @override 125 | CameraUpdate zoomTo(double zoom) { 126 | throw UnimplementedError(); 127 | } 128 | } 129 | 130 | class FakeCameraUpdate extends CameraUpdate {} 131 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: platform_maps_flutter 2 | 3 | environment: 4 | sdk: '>=3.0.0 <4.0.0' 5 | 6 | dev_dependencies: 7 | melos: ^6.0.0 --------------------------------------------------------------------------------