├── .vscode
└── launch.json
├── LICENSE
├── README.md
├── example
├── .gitignore
├── .metadata
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── flutter_floating_map_marker_titles_demo
│ │ │ │ │ └── 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
│ ├── 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
│ └── RunnerTests
│ │ └── RunnerTests.swift
├── lib
│ ├── assets
│ │ ├── demo_data.dart
│ │ └── images
│ │ │ └── marker.png
│ ├── drawer
│ │ └── drawer.dart
│ ├── main.dart
│ └── pages
│ │ ├── abstract_demo_page.dart
│ │ ├── flutter_map
│ │ ├── abstract_flutter_map_demo_page.dart
│ │ ├── flutter_map_with_layer.dart
│ │ ├── flutter_map_wrapped_data.dart
│ │ └── flutter_map_wrapped_streams.dart
│ │ └── google_maps
│ │ └── google_maps.dart
├── pubspec.lock
├── pubspec.yaml
├── test
│ └── widget_test.dart
└── web
│ ├── favicon.png
│ ├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
│ ├── index.html
│ └── manifest.json
├── flutter_floating_map_marker_titles_core
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── lib
│ ├── controller
│ │ ├── cache
│ │ │ ├── epsg_3857_proj_cache.dart
│ │ │ └── text_painting_cache.dart
│ │ ├── display
│ │ │ ├── floating_title_painter.dart
│ │ │ ├── layer
│ │ │ │ ├── title_layer_background_painter.dart
│ │ │ │ ├── title_layer_foreground_painter.dart
│ │ │ │ └── title_layer_painter.dart
│ │ │ └── titles_display_state.dart
│ │ ├── fmto_controller.dart
│ │ └── map_view_interface
│ │ │ ├── abstract_czr_map_view_interface.dart
│ │ │ └── abstract_map_view_interface.dart
│ ├── model
│ │ └── floating_marker_title_info.dart
│ ├── utils
│ │ ├── cached_calculator.dart
│ │ ├── geo
│ │ │ ├── bounds.dart
│ │ │ ├── crs.dart
│ │ │ └── point.dart
│ │ ├── rotating_cache.dart
│ │ └── utils.dart
│ └── view
│ │ ├── abstract_map_view_wrapper.dart
│ │ ├── floating_marker_titles_overlay.dart
│ │ └── floating_marker_titles_overlay_layer.dart
├── pubspec.lock
└── pubspec.yaml
├── flutter_map_floating_marker_titles
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── lib
│ └── flutter_map_floating_marker_titles.dart
├── pubspec.lock
└── pubspec.yaml
├── google_maps_flutter_floating_marker_titles
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── lib
│ └── google_maps_flutter_floating_marker_titles.dart
├── pubspec.lock
└── pubspec.yaml
├── publish_checklist.md
└── visual_demo.gif
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "FMFMT",
9 | "cwd": "example",
10 | "request": "launch",
11 | "type": "dart"
12 | },
13 | {
14 | "name": "FMFMT Profiling",
15 | "cwd": "example",
16 | "request": "launch",
17 | "type": "dart",
18 | "flutterMode": "profile"
19 | }
20 | ]
21 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, androidseb
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Flutter Floating Map Marker Titles
2 |
3 | This library is inspired from [android-google-maps-floating-marker-titles](https://github.com/androidseb/android-google-maps-floating-marker-titles) and aims to achieve the same thing on Flutter apps.
4 |
5 | I had initially built this library as an experiment to gauge how well native-like things can be achieved with Flutter (e.g. real-time drawing on a Canvas), and I've been very happy with the results, this library is now used in my production app [Map Marker](https://mapmarker.app) running on [Android](https://play.google.com/store/apps/details?id=com.exlyo.mapmarker), [iOS](https://itunes.apple.com/us/app/map-marker-places-organizer/id1287281807) and [Web](https://www.mapmarker.app/webapp/).
6 |
7 | This library is useful if you want to see the titles of the markers on the map floating next to the marker. It attempts to reproduce the behavior for labels of points of interest shown in map applications. It works as a wrapper of existing map view widgets for the following libraries:
8 | * [Flutter Map](https://github.com/fleaflet/flutter_map)
9 | * [Google Maps Flutter](https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter)
10 |
11 | ## Visual Preview
12 |
13 | This is how it looks like, from the example sample app of this library:
14 |
15 |
16 |
17 | ## Project structure
18 |
19 | This project is divided into the following main folders:
20 | * `flutter_floating_map_marker_titles_core`: the core code of the floating map marker titles library, meant to be agnostic of any map view implementation, this is the source code of the [flutter_floating_map_marker_titles_core](https://pub.dev/packages/flutter_floating_map_marker_titles_core) library
21 | * `flutter_map_floating_marker_titles`: the code of the floating map marker titles library for [Flutter Map](https://github.com/fleaflet/flutter_map), this is the source code of the [flutter_map_floating_marker_titles](https://pub.dev/packages/flutter_map_floating_marker_titles) library
22 | * `google_maps_flutter_floating_marker_titles`: the code of the floating map marker titles library for [Google Maps Flutter](https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter), this is the source code of the [google_maps_flutter_floating_marker_titles](https://pub.dev/packages/google_maps_flutter_floating_marker_titles) library
23 | * `example`: a simple example of a flutter application show-casing the use of the libraries
24 |
25 | ## Sample app setup
26 |
27 | In the sample app, the [Flutter Map](https://github.com/fleaflet/flutter_map) example will work out of the box, but for the [Google Maps Flutter](https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter) example to work, you will need to update the following file, based on the [Google Maps Flutter library getting started instructions](https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter#getting-started):
28 | * `example/android/app/src/main/AndroidManifest.xml`
29 | * `example/ios/Runner/AppDelegate.swift`
30 |
31 | ## How to use this library in your code
32 |
33 | For a working example, see the flutter app project in the `example` folder of this repo.
34 |
35 | ### Step 1: depend on the library
36 |
37 | Add `flutter_map_floating_marker_titles` and/or `google_maps_flutter_floating_marker_titles` to your pubspec:
38 |
39 | ```yaml
40 | dependencies:
41 | flutter_map_floating_marker_titles: any # or the latest version on Pub
42 | google_maps_flutter_floating_marker_titles: any # or the latest version on Pub
43 | ```
44 |
45 | ### Step 2: create the FMTOOptions object
46 |
47 | ```dart
48 | final FMTOOptions fmtoOptions = FMTOOptions();
49 | ```
50 |
51 | ### Step 3: create the list of FloatingMarkerTitleInfo items
52 |
53 | ```dart
54 | final List floatingTitles = [];
55 | floatingTitles.add(FloatingMarkerTitleInfo(
56 | id: 0,
57 | latLng: LatLng(0, 0),
58 | title: 'A floating title',
59 | color: Colors.green,
60 | ));
61 | ```
62 |
63 | ### Step 4a: Create the Flutter Map View
64 |
65 | ```dart
66 | // With the FlutterMapWithFMTO widget as a FlutterMap wrapper
67 | FlutterMapWithFMTO(
68 | floatingTitles: floatingTitles,
69 | fmtoOptions: fmtoOptions,
70 | // ... other than the 2 above option, this widget takes
71 | // exactly the same props as the FlutterMap widget.
72 | options: MapOptions(
73 | center: LatLng(0, 0),
74 | zoom: 13,
75 | ),
76 | children: [
77 | TileLayer(
78 | urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
79 | ),
80 | ],
81 | )
82 |
83 | // Or with the FloatingMarkerTitlesLayer widget as a FlutterMap layer
84 | FlutterMap(
85 | options: MapOptions(
86 | center: LatLng(0, 0),
87 | zoom: 13,
88 | ),
89 | children: [
90 | TileLayer(
91 | urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
92 | ),
93 | FloatingMarkerTitlesLayer(
94 | floatingTitles: floatingTitles,
95 | fmtoOptions: fmtoOptions,
96 | ),
97 | ],
98 | )
99 | ```
100 |
101 | ### Step 4b: Create the Google Maps View
102 |
103 | ```dart
104 | GoogleMapWithFMTO(
105 | floatingTitles: floatingTitles,
106 | fmtoOptions: fmtoOptions,
107 | // ... other than the 2 above option, this widget takes
108 | // exactly the same props as the GoogleMap widget.
109 | initialCameraPosition: CameraPosition(
110 | target: LatLng(0, 0),
111 | zoom: 13,
112 | ),
113 | )
114 | ```
115 |
116 | ## Library features
117 |
118 | ### Overall features
119 |
120 | * Display floating markers titles on top of the map
121 | * Automatically avoids overlap between floating marker titles, will not display a title if overlapping with others
122 | * Marker title text transparent outline for better visuals: the text will be readable no matter the map background and the outline color will adapt to white or black depending on the text color's luminance (perceived brightness)
123 | * Marker title fade-in animation for better visuals
124 |
125 | ### View-wide customization options
126 |
127 | ```dart
128 | FMTOOptions(
129 | // The number of milliseconds between two repaints of the titles layer. 60 frames per seconds = 16 milliseconds between each frame.
130 | repaintIntervalMillis: 16,
131 | // Titles text size
132 | textSize: 14.0,
133 | // Maximum number of floating titles
134 | maxTitlesCount: 30,
135 | // Maximum width of floating titles
136 | maxTitlesWidth: 150,
137 | // Maximum lines count of floating titles
138 | maxTitleLines: 2,
139 | // Maximum number of cached, pre-laid out, ready to draw floating titles info, since computing the layout of text is an expensive operation
140 | textPaintingCacheSize: 2000,
141 | // Maximum number of cached coordinates by the map coordinates projections calculator
142 | mapProjectionsCacheSize: 10000,
143 | // No performance drop with more markers once the maximum number of floating titles has been reached, since the library only scans for a limited number of markers per frame, which can be set with titlesToCheckPerFrame
144 | titlesToCheckPerFrame: 30,
145 | // Time in milliseconds of the title fade-in animation
146 | fadeInAnimationTimeMillis: 300,
147 | // Titles placement option with anchor and margin
148 | titlePlacementPolicy: const FloatingMarkerPlacementPolicy(FloatingMarkerGravity.right, 12),
149 | );
150 | ```
151 |
152 | ### Per-title customization options
153 |
154 | ```dart
155 | FloatingMarkerTitleInfo(
156 | // ID of the floating title, used by the system to track what was added/removed between two paints
157 | id: 0,
158 | // Base coordinates the title is attached to
159 | latLng: LatLng(0, 0),
160 | // The title text as a String
161 | title: 'The title',
162 | // The title base color
163 | color: Colors.green,
164 | // Whether the title text should be written in bold
165 | isBold: false,
166 | // z-index of the title to specify which title has the most priority for display in case of titles collisions
167 | zIndex: 1,
168 | );
169 | ```
170 |
171 | ## Known limitations
172 |
173 | * Does not work in web for [Google Maps Flutter](https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter)
174 | * Works poorly with Google Maps on Android - when moving the map around, the titles visually lag behind: this is due to a bug in the [google_maps_flutter_android](https://pub.dev/packages/google_maps_flutter_android) library reported [here](https://github.com/flutter/flutter/issues/169152)
175 |
176 | ## About issues and/or feature requests
177 |
178 | I am not willing to invest time to take feature requests at the moment, but if you find a bug, I'll probably want to fix it, so feel free to report any bugs you may find.
179 |
180 | If you need a feature and want to build it and then submit it as a pull request, I'm willing to work with you to merge your work into the current code.
181 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .build/
9 | .buildlog/
10 | .history
11 | .svn/
12 | .swiftpm/
13 | migrate_working_dir/
14 |
15 | # IntelliJ related
16 | *.iml
17 | *.ipr
18 | *.iws
19 | .idea/
20 |
21 | # The .vscode folder contains launch configuration and tasks you configure in
22 | # VS Code which you may wish to be included in version control, so this line
23 | # is commented out by default.
24 | #.vscode/
25 |
26 | # Flutter/Dart/Pub related
27 | **/doc/api/
28 | **/ios/Flutter/.last_build_id
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .pub-cache/
33 | .pub/
34 | /build/
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Android Studio will place build artifacts here
43 | /android/app/debug
44 | /android/app/profile
45 | /android/app/release
46 |
--------------------------------------------------------------------------------
/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: "68415ad1d920f6fe5ec284f5c2febf7c4dd5b0b3"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 68415ad1d920f6fe5ec284f5c2febf7c4dd5b0b3
17 | base_revision: 68415ad1d920f6fe5ec284f5c2febf7c4dd5b0b3
18 | - platform: android
19 | create_revision: 68415ad1d920f6fe5ec284f5c2febf7c4dd5b0b3
20 | base_revision: 68415ad1d920f6fe5ec284f5c2febf7c4dd5b0b3
21 | - platform: ios
22 | create_revision: 68415ad1d920f6fe5ec284f5c2febf7c4dd5b0b3
23 | base_revision: 68415ad1d920f6fe5ec284f5c2febf7c4dd5b0b3
24 |
25 | # User provided section
26 |
27 | # List of Local paths (relative to this file) that should be
28 | # ignored by the migrate tool.
29 | #
30 | # Files that are not part of the templates will be ignored by default.
31 | unmanaged_files:
32 | - 'lib/main.dart'
33 | - 'ios/Runner.xcodeproj/project.pbxproj'
34 |
--------------------------------------------------------------------------------
/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/to/reference-keystore
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5 | id "dev.flutter.flutter-gradle-plugin"
6 | }
7 |
8 | android {
9 | namespace = "com.example.flutter_floating_map_marker_titles_demo"
10 | compileSdk = flutter.compileSdkVersion
11 | ndkVersion = flutter.ndkVersion
12 |
13 | compileOptions {
14 | sourceCompatibility = JavaVersion.VERSION_1_8
15 | targetCompatibility = JavaVersion.VERSION_1_8
16 | }
17 |
18 | kotlinOptions {
19 | jvmTarget = JavaVersion.VERSION_1_8
20 | }
21 |
22 | defaultConfig {
23 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24 | applicationId = "com.example.flutter_floating_map_marker_titles_demo"
25 | // You can update the following values to match your application needs.
26 | // For more information, see: https://flutter.dev/to/review-gradle-config.
27 | minSdk = flutter.minSdkVersion
28 | targetSdk = flutter.targetSdkVersion
29 | versionCode = flutter.versionCode
30 | versionName = flutter.versionName
31 | }
32 |
33 | buildTypes {
34 | release {
35 | // TODO: Add your own signing config for the release build.
36 | // Signing with the debug keys for now, so `flutter run --release` works.
37 | signingConfig = signingConfigs.debug
38 | }
39 | }
40 | }
41 |
42 | flutter {
43 | source = "../.."
44 | }
45 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
18 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
33 |
36 |
38 |
39 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/com/example/flutter_floating_map_marker_titles_demo/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.flutter_floating_map_marker_titles_demo
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity()
6 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | rootProject.buildDir = "../build"
9 | subprojects {
10 | project.buildDir = "${rootProject.buildDir}/${project.name}"
11 | }
12 | subprojects {
13 | project.evaluationDependsOn(":app")
14 | }
15 |
16 | tasks.register("clean", Delete) {
17 | delete rootProject.buildDir
18 | }
19 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
6 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }()
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21 | id "com.android.application" version "8.1.0" apply false
22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false
23 | }
24 |
25 | include ":app"
26 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
63 |
65 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import GoogleMaps
4 |
5 | @main
6 | @objc class AppDelegate: FlutterAppDelegate {
7 | override func application(
8 | _ application: UIApplication,
9 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
10 | ) -> Bool {
11 | GMSServices.provideAPIKey("YOUR KEY HERE")
12 | GeneratedPluginRegistrant.register(with: self)
13 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Flutter Floating Map Marker Titles Demo
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | flutter_floating_map_marker_titles_demo
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | CADisableMinimumFrameDurationOnPhone
45 |
46 | UIApplicationSupportsIndirectInputEvents
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/example/lib/assets/demo_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:latlong2/latlong.dart';
3 |
4 | const String APP_TITLE = 'Floating markers demo';
5 | const String FLUTTER_MAP_HELP_DIALOG_MESSAGE = '''
6 | You can tap on the map to add markers with floating titles.
7 | You can use the slider at the top to rotate the map too.
8 | This example uses the 'fleaflet' flutter library to display the map.
9 | ''';
10 | const String GOOGLE_MAPS_HELP_DIALOG_MESSAGE = '''
11 | You can tap on the map to add markers with floating titles.
12 | You can use the pinch gesture to rotate the map too.
13 | This example uses the 'google_maps_flutter' flutter library to display the map.
14 | ''';
15 | const String OK_BUTTON_TEXT = 'OK';
16 | const String ROTATION_LABEL_TEXT = 'Rotation';
17 | // ignore: non_constant_identifier_names
18 | LatLng INITIAL_MAP_LOCATION = LatLng(47.2378, 6.0241);
19 | const double INITIAL_MAP_ZOOM = 13.0;
20 | const String MARKER_ICON_ASSET_PATH = 'lib/assets/images/marker.png';
21 | const List COLORS = [
22 | Colors.amber,
23 | Colors.blue,
24 | Colors.blueGrey,
25 | Colors.brown,
26 | Colors.cyan,
27 | Colors.deepOrange,
28 | Colors.deepPurple,
29 | Colors.green,
30 | Colors.grey,
31 | Colors.indigo,
32 | Colors.lightBlue,
33 | Colors.lightGreen,
34 | Colors.lime,
35 | Colors.orange,
36 | Colors.pink,
37 | Colors.purple,
38 | Colors.red,
39 | Colors.teal,
40 | Colors.yellow,
41 | Colors.black,
42 | Colors.white,
43 | ];
44 | const List MARKER_NAMES = [
45 | 'Marker',
46 | 'A marker with a moderately long name',
47 | 'A marker with a somewhat long long long long long long long long name',
48 | 'A marker with a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long name',
49 | 'Some marker',
50 | 'Some other marker',
51 | 'Bakery',
52 | 'A',
53 | 'B',
54 | 'Restaurant',
55 | 'Some lake',
56 | ];
57 |
--------------------------------------------------------------------------------
/example/lib/assets/images/marker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/lib/assets/images/marker.png
--------------------------------------------------------------------------------
/example/lib/drawer/drawer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/flutter_map_with_layer.dart';
3 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/flutter_map_wrapped_data.dart';
4 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/flutter_map_wrapped_streams.dart';
5 | import 'package:flutter_floating_map_marker_titles_demo/pages/google_maps/google_maps.dart';
6 | import 'package:flutter_floating_map_marker_titles_demo/assets/demo_data.dart' as demo_data;
7 |
8 | Widget _buildMenuItem(final BuildContext context, final String routeName, final String currentRoute) {
9 | bool isSelected = routeName == currentRoute;
10 |
11 | return ListTile(
12 | title: Text(routeName),
13 | selected: isSelected,
14 | onTap: () {
15 | if (isSelected) {
16 | Navigator.pop(context);
17 | } else {
18 | Navigator.pushReplacementNamed(context, routeName);
19 | }
20 | },
21 | );
22 | }
23 |
24 | Drawer buildDrawer(final BuildContext context, final String currentRoute) {
25 | return Drawer(
26 | child: ListView(
27 | children: [
28 | const DrawerHeader(
29 | child: Center(
30 | child: Text(demo_data.APP_TITLE),
31 | ),
32 | ),
33 | _buildMenuItem(
34 | context,
35 | FlutterMapLayerDemoPage.route,
36 | currentRoute,
37 | ),
38 | _buildMenuItem(
39 | context,
40 | FlutterMapDWrapperDemoPage.route,
41 | currentRoute,
42 | ),
43 | _buildMenuItem(
44 | context,
45 | FlutterMapSWrapperDemoPage.route,
46 | currentRoute,
47 | ),
48 | _buildMenuItem(
49 | context,
50 | GoogleMapsDemoPage.route,
51 | currentRoute,
52 | ),
53 | ],
54 | ),
55 | );
56 | }
57 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'package:flutter_floating_map_marker_titles_demo/assets/demo_data.dart' as demo_data;
4 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/flutter_map_with_layer.dart';
5 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/flutter_map_wrapped_data.dart';
6 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/flutter_map_wrapped_streams.dart';
7 | import 'package:flutter_floating_map_marker_titles_demo/pages/google_maps/google_maps.dart';
8 |
9 | void main() {
10 | runApp(DemoApp());
11 | }
12 |
13 | class DemoApp extends StatelessWidget {
14 | @override
15 | Widget build(final BuildContext context) {
16 | return MaterialApp(
17 | debugShowCheckedModeBanner: false,
18 | title: demo_data.APP_TITLE,
19 | theme: ThemeData(
20 | primarySwatch: Colors.blue,
21 | ),
22 | home: FlutterMapLayerDemoPage(),
23 | routes: {
24 | FlutterMapLayerDemoPage.route: (context) => FlutterMapLayerDemoPage(),
25 | FlutterMapDWrapperDemoPage.route: (context) => FlutterMapDWrapperDemoPage(),
26 | FlutterMapSWrapperDemoPage.route: ((context) => FlutterMapSWrapperDemoPage()),
27 | GoogleMapsDemoPage.route: (context) => GoogleMapsDemoPage(),
28 | },
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/example/lib/pages/abstract_demo_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
4 | import 'package:flutter_floating_map_marker_titles_core/model/floating_marker_title_info.dart';
5 | import 'package:flutter_floating_map_marker_titles_demo/drawer/drawer.dart';
6 | import 'package:latlong2/latlong.dart';
7 | import 'package:flutter_floating_map_marker_titles_demo/assets/demo_data.dart' as demo_data;
8 |
9 | abstract class AbstractDemoPage extends StatefulWidget {
10 | AbstractDemoPage({final Key? key}) : super(key: key);
11 | @override
12 | AbstractDemoPageState createState();
13 | }
14 |
15 | abstract class AbstractDemoPageState extends State> {
16 | final List markers = [];
17 | final List floatingTitles = [];
18 |
19 | M createMarker(final LatLng latLng);
20 |
21 | String getTitleText();
22 |
23 | String getHelpMessageText();
24 |
25 | String getPageRouteString();
26 |
27 | Widget buildMapWidget(final BuildContext context, final Function(LatLng) createNewMarkerCallback);
28 |
29 | FMTOOptions createFMTOOptions() {
30 | // You can specify the Floating Marker Titles Overlay options here
31 | return FMTOOptions();
32 | }
33 |
34 | @protected
35 | void addMarker(final LatLng latLng) {
36 | setState(() {
37 | addMarkerToData(latLng);
38 | });
39 | }
40 |
41 | @nonVirtual
42 | @protected
43 | void addMarkerToData(final LatLng latLng) {
44 | markers.add(createMarker(latLng));
45 | floatingTitles.add(FloatingMarkerTitleInfo(
46 | id: floatingTitles.length + 1,
47 | latLng: latLng,
48 | title: demo_data.MARKER_NAMES[floatingTitles.length % demo_data.MARKER_NAMES.length] +
49 | ' ${floatingTitles.length + 1}',
50 | color: demo_data.COLORS[floatingTitles.length % demo_data.COLORS.length],
51 | zIndex: floatingTitles.length + 1,
52 | ));
53 | }
54 |
55 | Future _showHelpMessageDialog(final BuildContext context) async {
56 | return showDialog(
57 | context: context,
58 | builder: (BuildContext context) {
59 | return AlertDialog(
60 | title: Text(getTitleText()),
61 | content: SingleChildScrollView(
62 | child: ListBody(
63 | children: [
64 | Text(getHelpMessageText()),
65 | ],
66 | ),
67 | ),
68 | actions: [
69 | TextButton(
70 | child: Text(demo_data.OK_BUTTON_TEXT),
71 | onPressed: () {
72 | Navigator.of(context).pop();
73 | },
74 | ),
75 | ],
76 | );
77 | },
78 | );
79 | }
80 |
81 | @override
82 | Widget build(final BuildContext context) {
83 | return Scaffold(
84 | appBar: AppBar(
85 | title: Text(getTitleText()),
86 | actions: [
87 | IconButton(
88 | icon: Icon(Icons.help),
89 | onPressed: () {
90 | _showHelpMessageDialog(context);
91 | },
92 | )
93 | ],
94 | ),
95 | drawer: buildDrawer(context, getPageRouteString()),
96 | body: buildMapWidget(context, (final LatLng newMarkerLatLng) {
97 | addMarker(newMarkerLatLng);
98 | }),
99 | );
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/example/lib/pages/flutter_map/abstract_flutter_map_demo_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_floating_map_marker_titles_demo/pages/abstract_demo_page.dart';
4 | import 'package:flutter_map/flutter_map.dart';
5 | import 'package:latlong2/latlong.dart';
6 | import 'package:flutter_floating_map_marker_titles_demo/assets/demo_data.dart' as demo_data;
7 |
8 | abstract class AbstractFlutterMapDemoPage extends AbstractDemoPage {
9 | AbstractFlutterMapDemoPage({final Key? key}) : super(key: key);
10 | }
11 |
12 | abstract class AbstractFlutterMapDemoPageState extends AbstractDemoPageState {
13 | final MapController mapController = MapController();
14 | double currentRotation = 0;
15 |
16 | @override
17 | String getHelpMessageText() {
18 | return demo_data.FLUTTER_MAP_HELP_DIALOG_MESSAGE;
19 | }
20 |
21 | @override
22 | Marker createMarker(final LatLng latLng) {
23 | return Marker(
24 | point: latLng,
25 | width: 14,
26 | height: 20,
27 | alignment: Alignment.topCenter,
28 | rotate: true,
29 | child: Container(
30 | child: Image.asset(
31 | demo_data.MARKER_ICON_ASSET_PATH,
32 | fit: BoxFit.fitHeight,
33 | width: 28,
34 | height: 40,
35 | ),
36 | ),
37 | );
38 | }
39 |
40 | @nonVirtual
41 | @override
42 | Widget buildMapWidget(final BuildContext context, final Function(LatLng) createNewMarkerCallback) {
43 | return Column(
44 | children: [
45 | Padding(
46 | padding: EdgeInsets.fromLTRB(16, 4, 16, 4),
47 | child: Row(
48 | children: [
49 | Text(demo_data.ROTATION_LABEL_TEXT),
50 | Flexible(
51 | child: Slider(
52 | value: currentRotation,
53 | min: 0,
54 | max: 360,
55 | onChanged: (final double newRotationValue) {
56 | mapController.rotate(newRotationValue);
57 | setState(() {
58 | currentRotation = newRotationValue;
59 | });
60 | },
61 | ),
62 | ),
63 | ],
64 | ),
65 | ),
66 | Flexible(
67 | child: buildMapWidgetImpl(
68 | context,
69 | MapOptions(
70 | initialCenter: demo_data.INITIAL_MAP_LOCATION,
71 | initialZoom: demo_data.INITIAL_MAP_ZOOM,
72 | onTap: (final TapPosition tapPosition, final LatLng latLng) {
73 | createNewMarkerCallback(latLng);
74 | },
75 | ),
76 | TileLayer(
77 | urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
78 | userAgentPackageName: 'com.flutter_map_floating_marker_titles.example',
79 | ),
80 | createNewMarkerCallback,
81 | ),
82 | ),
83 | ],
84 | );
85 | }
86 |
87 | @protected
88 | Widget buildMapWidgetImpl(
89 | final BuildContext context,
90 | final MapOptions mapOptions,
91 | final Widget backgroundLayer,
92 | final Function(LatLng) createNewMarkerCallback,
93 | );
94 | }
95 |
--------------------------------------------------------------------------------
/example/lib/pages/flutter_map/flutter_map_with_layer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/abstract_flutter_map_demo_page.dart';
3 | import 'package:flutter_map/flutter_map.dart';
4 | import 'package:flutter_map_floating_marker_titles/flutter_map_floating_marker_titles.dart';
5 | import 'package:latlong2/latlong.dart';
6 |
7 | class FlutterMapLayerDemoPage extends AbstractFlutterMapDemoPage {
8 | static const String route = 'Flutter Map - Layer';
9 |
10 | FlutterMapLayerDemoPage({final Key? key}) : super(key: key);
11 | @override
12 | _FlutterMapLayerLayerDemoPageState createState() => _FlutterMapLayerLayerDemoPageState();
13 | }
14 |
15 | class _FlutterMapLayerLayerDemoPageState extends AbstractFlutterMapDemoPageState {
16 | @override
17 | String getTitleText() {
18 | return FlutterMapLayerDemoPage.route;
19 | }
20 |
21 | @override
22 | String getPageRouteString() {
23 | return FlutterMapLayerDemoPage.route;
24 | }
25 |
26 | @override
27 | Widget buildMapWidgetImpl(
28 | final BuildContext context,
29 | final MapOptions mapOptions,
30 | final Widget backgroundLayer,
31 | final Function(LatLng) createNewMarkerCallback,
32 | ) {
33 | return FlutterMap(
34 | mapController: mapController,
35 | options: mapOptions,
36 | children: [
37 | backgroundLayer,
38 | MarkerLayer(
39 | markers: markers,
40 | ),
41 | FloatingMarkerTitlesLayer(
42 | floatingTitles: floatingTitles,
43 | fmtoOptions: createFMTOOptions(),
44 | ),
45 | ],
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/lib/pages/flutter_map/flutter_map_wrapped_data.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/abstract_flutter_map_demo_page.dart';
3 | import 'package:flutter_map/flutter_map.dart';
4 | import 'package:flutter_map_floating_marker_titles/flutter_map_floating_marker_titles.dart';
5 | import 'package:latlong2/latlong.dart';
6 |
7 | class FlutterMapDWrapperDemoPage extends AbstractFlutterMapDemoPage {
8 | static const String route = 'Flutter Map - Wrapper + Data';
9 |
10 | FlutterMapDWrapperDemoPage({final Key? key}) : super(key: key);
11 | @override
12 | _FlutterMapDWrapperDemoPageState createState() => _FlutterMapDWrapperDemoPageState();
13 | }
14 |
15 | class _FlutterMapDWrapperDemoPageState extends AbstractFlutterMapDemoPageState {
16 | @override
17 | String getTitleText() {
18 | return FlutterMapDWrapperDemoPage.route;
19 | }
20 |
21 | @override
22 | String getPageRouteString() {
23 | return FlutterMapDWrapperDemoPage.route;
24 | }
25 |
26 | @override
27 | Widget buildMapWidgetImpl(
28 | final BuildContext context,
29 | final MapOptions mapOptions,
30 | final Widget backgroundLayer,
31 | final Function(LatLng) createNewMarkerCallback,
32 | ) {
33 | return FlutterMapWithFMTO(
34 | floatingTitles: floatingTitles,
35 | fmtoOptions: createFMTOOptions(),
36 | mapController: mapController,
37 | options: mapOptions,
38 | children: [
39 | backgroundLayer,
40 | MarkerLayer(
41 | markers: markers,
42 | ),
43 | ],
44 | );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/example/lib/pages/flutter_map/flutter_map_wrapped_streams.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_floating_map_marker_titles_demo/pages/flutter_map/abstract_flutter_map_demo_page.dart';
5 | import 'package:flutter_map/flutter_map.dart';
6 | import 'package:flutter_map_floating_marker_titles/flutter_map_floating_marker_titles.dart';
7 | import 'package:latlong2/latlong.dart';
8 | import 'package:flutter_floating_map_marker_titles_core/model/floating_marker_title_info.dart';
9 |
10 | class FlutterMapSWrapperDemoPage extends AbstractFlutterMapDemoPage {
11 | static const String route = 'Flutter Map - Wrapper + Stream';
12 |
13 | FlutterMapSWrapperDemoPage({final Key? key}) : super(key: key);
14 | @override
15 | _FlutterMapSWrapperDemoPageState createState() => _FlutterMapSWrapperDemoPageState();
16 | }
17 |
18 | class _FlutterMapSWrapperDemoPageState extends AbstractFlutterMapDemoPageState {
19 | final StreamController> _floatingTitlesSC = StreamController();
20 | final StreamController> _markersSC = StreamController();
21 |
22 | @override
23 | void addMarker(LatLng latLng) {
24 | addMarkerToData(latLng);
25 | _markersSC.add(markers);
26 | _floatingTitlesSC.add(floatingTitles);
27 | }
28 |
29 | @override
30 | String getTitleText() {
31 | return FlutterMapSWrapperDemoPage.route;
32 | }
33 |
34 | @override
35 | String getPageRouteString() {
36 | return FlutterMapSWrapperDemoPage.route;
37 | }
38 |
39 | @override
40 | Widget buildMapWidgetImpl(
41 | final BuildContext context,
42 | final MapOptions mapOptions,
43 | final Widget backgroundLayer,
44 | final Function(LatLng) createNewMarkerCallback,
45 | ) {
46 | return FlutterMapWithFMTO(
47 | floatingTitlesStream: _floatingTitlesSC.stream,
48 | floatingTitles: floatingTitles,
49 | fmtoOptions: createFMTOOptions(),
50 | mapController: mapController,
51 | options: mapOptions,
52 | children: [
53 | backgroundLayer,
54 | StreamBuilder(
55 | stream: _markersSC.stream,
56 | builder: (context, snapshot) {
57 | return MarkerLayer(
58 | markers: markers,
59 | );
60 | },
61 | ),
62 | ],
63 | );
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/example/lib/pages/google_maps/google_maps.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:flutter_floating_map_marker_titles_demo/assets/demo_data.dart' as demo_data;
4 | import 'package:flutter_floating_map_marker_titles_demo/pages/abstract_demo_page.dart';
5 | import 'package:google_maps_flutter/google_maps_flutter.dart';
6 | import 'package:google_maps_flutter_floating_marker_titles/google_maps_flutter_floating_marker_titles.dart';
7 | import 'package:latlong2/latlong.dart' as latlong;
8 |
9 | class GoogleMapsDemoPage extends AbstractDemoPage {
10 | static const String route = 'Google Maps';
11 |
12 | GoogleMapsDemoPage({final Key? key}) : super(key: key);
13 | @override
14 | _GoogleMapsDemoPageState createState() => _GoogleMapsDemoPageState();
15 | }
16 |
17 | int markerId = 0;
18 |
19 | class _GoogleMapsDemoPageState extends AbstractDemoPageState {
20 | BitmapDescriptor? _markerIcon;
21 |
22 | BitmapDescriptor createBitmapDescriptorFromBytes(Uint8List bytes) {
23 | // Note that the correct non-deprecated code should be:
24 | // return BitmapDescriptor.bytes(
25 | // bytes,
26 | // bitmapScaling: MapBitmapScaling.none,
27 | // );
28 | // However at the current time, bitmapScaling is not working on iOS:
29 | // https://github.com/flutter/flutter/issues/165212
30 | // Using the deprecated method instead which works for both Android and iOS.
31 | // ignore: deprecated_member_use
32 | return BitmapDescriptor.fromBytes(bytes);
33 | }
34 |
35 | Future _createMarkerImageFromAsset(final BuildContext context) async {
36 | if (_markerIcon == null) {
37 | final bytes = Uint8List.sublistView(await rootBundle.load(demo_data.MARKER_ICON_ASSET_PATH));
38 | final BitmapDescriptor bitmapDescriptor = createBitmapDescriptorFromBytes(bytes);
39 | _updateBitmap(bitmapDescriptor);
40 | }
41 | }
42 |
43 | void _updateBitmap(final BitmapDescriptor bitmap) {
44 | setState(() {
45 | _markerIcon = bitmap;
46 | });
47 | }
48 |
49 | @override
50 | Widget buildMapWidget(final BuildContext context, final Function(latlong.LatLng) createNewMarkerCallback) {
51 | _createMarkerImageFromAsset(context);
52 | return Column(
53 | children: [
54 | Flexible(
55 | child: GoogleMapWithFMTO(
56 | floatingTitles: floatingTitles,
57 | fmtoOptions: createFMTOOptions(),
58 | initialCameraPosition: CameraPosition(
59 | target: LatLng(
60 | demo_data.INITIAL_MAP_LOCATION.latitude,
61 | demo_data.INITIAL_MAP_LOCATION.longitude,
62 | ),
63 | zoom: demo_data.INITIAL_MAP_ZOOM,
64 | ),
65 | onTap: (final LatLng latLng) {
66 | createNewMarkerCallback(latlong.LatLng(latLng.latitude, latLng.longitude));
67 | },
68 | markers: _buildMarkersSet(),
69 | ),
70 | ),
71 | ],
72 | );
73 | }
74 |
75 | Set _buildMarkersSet() {
76 | final Set res = {};
77 | res.addAll(markers);
78 | return res;
79 | }
80 |
81 | @override
82 | Marker createMarker(final latlong.LatLng latLng) {
83 | return Marker(
84 | markerId: MarkerId('${markerId++}'),
85 | position: LatLng(latLng.latitude, latLng.longitude),
86 | icon: _markerIcon!,
87 | );
88 | }
89 |
90 | @override
91 | String getTitleText() {
92 | return GoogleMapsDemoPage.route;
93 | }
94 |
95 | @override
96 | String getHelpMessageText() {
97 | return demo_data.GOOGLE_MAPS_HELP_DIALOG_MESSAGE;
98 | }
99 |
100 | @override
101 | String getPageRouteString() {
102 | return GoogleMapsDemoPage.route;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.1"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.19.0"
44 | csslib:
45 | dependency: transitive
46 | description:
47 | name: csslib
48 | sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.0.2"
52 | dart_earcut:
53 | dependency: transitive
54 | description:
55 | name: dart_earcut
56 | sha256: e485001bfc05dcbc437d7bfb666316182e3522d4c3f9668048e004d0eb2ce43b
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "1.2.0"
60 | fake_async:
61 | dependency: transitive
62 | description:
63 | name: fake_async
64 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
65 | url: "https://pub.dev"
66 | source: hosted
67 | version: "1.3.1"
68 | flutter:
69 | dependency: "direct main"
70 | description: flutter
71 | source: sdk
72 | version: "0.0.0"
73 | flutter_floating_map_marker_titles_core:
74 | dependency: "direct overridden"
75 | description:
76 | path: "../flutter_floating_map_marker_titles_core"
77 | relative: true
78 | source: path
79 | version: "1.1.1"
80 | flutter_map:
81 | dependency: "direct main"
82 | description:
83 | name: flutter_map
84 | sha256: bbf145e8220531f2f727608c431871c7457f3b134e513543913afd00fdc1cd47
85 | url: "https://pub.dev"
86 | source: hosted
87 | version: "8.1.0"
88 | flutter_map_floating_marker_titles:
89 | dependency: "direct overridden"
90 | description:
91 | path: "../flutter_map_floating_marker_titles"
92 | relative: true
93 | source: path
94 | version: "1.3.0"
95 | flutter_plugin_android_lifecycle:
96 | dependency: transitive
97 | description:
98 | name: flutter_plugin_android_lifecycle
99 | sha256: "5a1e6fb2c0561958d7e4c33574674bda7b77caaca7a33b758876956f2902eea3"
100 | url: "https://pub.dev"
101 | source: hosted
102 | version: "2.0.27"
103 | flutter_test:
104 | dependency: "direct dev"
105 | description: flutter
106 | source: sdk
107 | version: "0.0.0"
108 | flutter_web_plugins:
109 | dependency: transitive
110 | description: flutter
111 | source: sdk
112 | version: "0.0.0"
113 | google_maps:
114 | dependency: transitive
115 | description:
116 | name: google_maps
117 | sha256: "4d6e199c561ca06792c964fa24b2bac7197bf4b401c2e1d23e345e5f9939f531"
118 | url: "https://pub.dev"
119 | source: hosted
120 | version: "8.1.1"
121 | google_maps_flutter:
122 | dependency: "direct main"
123 | description:
124 | name: google_maps_flutter
125 | sha256: "621125e35e81ca39ef600e45243d2be93167e61def72bc7207b0c4a635c58506"
126 | url: "https://pub.dev"
127 | source: hosted
128 | version: "2.10.1"
129 | google_maps_flutter_android:
130 | dependency: transitive
131 | description:
132 | name: google_maps_flutter_android
133 | sha256: "721ffae2240e957c04b0de19ffd4b68580adb57a8224496b7fb55fad23aec98a"
134 | url: "https://pub.dev"
135 | source: hosted
136 | version: "2.14.13"
137 | google_maps_flutter_floating_marker_titles:
138 | dependency: "direct overridden"
139 | description:
140 | path: "../google_maps_flutter_floating_marker_titles"
141 | relative: true
142 | source: path
143 | version: "1.1.0"
144 | google_maps_flutter_ios:
145 | dependency: transitive
146 | description:
147 | name: google_maps_flutter_ios
148 | sha256: "6f798adb0aa1db5adf551f2e39e24bd06c8c0fbe4de912fb2d9b5b3f48147b02"
149 | url: "https://pub.dev"
150 | source: hosted
151 | version: "2.13.2"
152 | google_maps_flutter_platform_interface:
153 | dependency: transitive
154 | description:
155 | name: google_maps_flutter_platform_interface
156 | sha256: "970c8f766c02909c7be282dea923c971f83a88adaf07f8871d0aacebc3b07bb2"
157 | url: "https://pub.dev"
158 | source: hosted
159 | version: "2.11.1"
160 | google_maps_flutter_web:
161 | dependency: transitive
162 | description:
163 | name: google_maps_flutter_web
164 | sha256: a9fd5356d46f54744ced1ebedbbf212f3d2cb71e95d79b1d08690c1ec33dc584
165 | url: "https://pub.dev"
166 | source: hosted
167 | version: "0.5.10+1"
168 | html:
169 | dependency: transitive
170 | description:
171 | name: html
172 | sha256: "1fc58edeaec4307368c60d59b7e15b9d658b57d7f3125098b6294153c75337ec"
173 | url: "https://pub.dev"
174 | source: hosted
175 | version: "0.15.5"
176 | http:
177 | dependency: transitive
178 | description:
179 | name: http
180 | sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
181 | url: "https://pub.dev"
182 | source: hosted
183 | version: "1.3.0"
184 | http_parser:
185 | dependency: transitive
186 | description:
187 | name: http_parser
188 | sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
189 | url: "https://pub.dev"
190 | source: hosted
191 | version: "4.1.2"
192 | intl:
193 | dependency: transitive
194 | description:
195 | name: intl
196 | sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
197 | url: "https://pub.dev"
198 | source: hosted
199 | version: "0.20.2"
200 | latlong2:
201 | dependency: transitive
202 | description:
203 | name: latlong2
204 | sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe"
205 | url: "https://pub.dev"
206 | source: hosted
207 | version: "0.9.1"
208 | leak_tracker:
209 | dependency: transitive
210 | description:
211 | name: leak_tracker
212 | sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
213 | url: "https://pub.dev"
214 | source: hosted
215 | version: "10.0.7"
216 | leak_tracker_flutter_testing:
217 | dependency: transitive
218 | description:
219 | name: leak_tracker_flutter_testing
220 | sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
221 | url: "https://pub.dev"
222 | source: hosted
223 | version: "3.0.8"
224 | leak_tracker_testing:
225 | dependency: transitive
226 | description:
227 | name: leak_tracker_testing
228 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
229 | url: "https://pub.dev"
230 | source: hosted
231 | version: "3.0.1"
232 | lint:
233 | dependency: "direct dev"
234 | description:
235 | name: lint
236 | sha256: f4bd4dbaa39f4ae8836f2d1275f2f32bc68b3a8cce0a0735dd1f7a601f06682a
237 | url: "https://pub.dev"
238 | source: hosted
239 | version: "2.1.2"
240 | lists:
241 | dependency: transitive
242 | description:
243 | name: lists
244 | sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27"
245 | url: "https://pub.dev"
246 | source: hosted
247 | version: "1.0.1"
248 | logger:
249 | dependency: transitive
250 | description:
251 | name: logger
252 | sha256: be4b23575aac7ebf01f225a241eb7f6b5641eeaf43c6a8613510fc2f8cf187d1
253 | url: "https://pub.dev"
254 | source: hosted
255 | version: "2.5.0"
256 | matcher:
257 | dependency: transitive
258 | description:
259 | name: matcher
260 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
261 | url: "https://pub.dev"
262 | source: hosted
263 | version: "0.12.16+1"
264 | material_color_utilities:
265 | dependency: transitive
266 | description:
267 | name: material_color_utilities
268 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
269 | url: "https://pub.dev"
270 | source: hosted
271 | version: "0.11.1"
272 | meta:
273 | dependency: transitive
274 | description:
275 | name: meta
276 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
277 | url: "https://pub.dev"
278 | source: hosted
279 | version: "1.15.0"
280 | mgrs_dart:
281 | dependency: transitive
282 | description:
283 | name: mgrs_dart
284 | sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7
285 | url: "https://pub.dev"
286 | source: hosted
287 | version: "2.0.0"
288 | path:
289 | dependency: transitive
290 | description:
291 | name: path
292 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
293 | url: "https://pub.dev"
294 | source: hosted
295 | version: "1.9.0"
296 | plugin_platform_interface:
297 | dependency: transitive
298 | description:
299 | name: plugin_platform_interface
300 | sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
301 | url: "https://pub.dev"
302 | source: hosted
303 | version: "2.1.8"
304 | polylabel:
305 | dependency: transitive
306 | description:
307 | name: polylabel
308 | sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b"
309 | url: "https://pub.dev"
310 | source: hosted
311 | version: "1.0.1"
312 | proj4dart:
313 | dependency: transitive
314 | description:
315 | name: proj4dart
316 | sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e
317 | url: "https://pub.dev"
318 | source: hosted
319 | version: "2.1.0"
320 | sanitize_html:
321 | dependency: transitive
322 | description:
323 | name: sanitize_html
324 | sha256: "12669c4a913688a26555323fb9cec373d8f9fbe091f2d01c40c723b33caa8989"
325 | url: "https://pub.dev"
326 | source: hosted
327 | version: "2.1.0"
328 | sky_engine:
329 | dependency: transitive
330 | description: flutter
331 | source: sdk
332 | version: "0.0.0"
333 | source_span:
334 | dependency: transitive
335 | description:
336 | name: source_span
337 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
338 | url: "https://pub.dev"
339 | source: hosted
340 | version: "1.10.0"
341 | stack_trace:
342 | dependency: transitive
343 | description:
344 | name: stack_trace
345 | sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
346 | url: "https://pub.dev"
347 | source: hosted
348 | version: "1.12.0"
349 | stream_channel:
350 | dependency: transitive
351 | description:
352 | name: stream_channel
353 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
354 | url: "https://pub.dev"
355 | source: hosted
356 | version: "2.1.2"
357 | stream_transform:
358 | dependency: transitive
359 | description:
360 | name: stream_transform
361 | sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
362 | url: "https://pub.dev"
363 | source: hosted
364 | version: "2.1.1"
365 | string_scanner:
366 | dependency: transitive
367 | description:
368 | name: string_scanner
369 | sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
370 | url: "https://pub.dev"
371 | source: hosted
372 | version: "1.3.0"
373 | term_glyph:
374 | dependency: transitive
375 | description:
376 | name: term_glyph
377 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
378 | url: "https://pub.dev"
379 | source: hosted
380 | version: "1.2.1"
381 | test_api:
382 | dependency: transitive
383 | description:
384 | name: test_api
385 | sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
386 | url: "https://pub.dev"
387 | source: hosted
388 | version: "0.7.3"
389 | tuple:
390 | dependency: transitive
391 | description:
392 | name: tuple
393 | sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
394 | url: "https://pub.dev"
395 | source: hosted
396 | version: "2.0.2"
397 | typed_data:
398 | dependency: transitive
399 | description:
400 | name: typed_data
401 | sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
402 | url: "https://pub.dev"
403 | source: hosted
404 | version: "1.4.0"
405 | unicode:
406 | dependency: transitive
407 | description:
408 | name: unicode
409 | sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1"
410 | url: "https://pub.dev"
411 | source: hosted
412 | version: "0.3.1"
413 | vector_math:
414 | dependency: transitive
415 | description:
416 | name: vector_math
417 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
418 | url: "https://pub.dev"
419 | source: hosted
420 | version: "2.1.4"
421 | vm_service:
422 | dependency: transitive
423 | description:
424 | name: vm_service
425 | sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
426 | url: "https://pub.dev"
427 | source: hosted
428 | version: "14.3.0"
429 | web:
430 | dependency: transitive
431 | description:
432 | name: web
433 | sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
434 | url: "https://pub.dev"
435 | source: hosted
436 | version: "1.1.1"
437 | wkt_parser:
438 | dependency: transitive
439 | description:
440 | name: wkt_parser
441 | sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13"
442 | url: "https://pub.dev"
443 | source: hosted
444 | version: "2.0.0"
445 | sdks:
446 | dart: ">=3.6.0 <4.0.0"
447 | flutter: ">=3.27.0"
448 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_floating_map_marker_titles_demo
2 | description: A new Flutter project.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `flutter pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | version: 1.0.0+1
9 |
10 | environment:
11 | sdk: '>=2.17.1 <4.0.0'
12 |
13 | dependencies:
14 | flutter:
15 | sdk: flutter
16 | google_maps_flutter: ^2.2.0
17 | flutter_map: ^8.1.0
18 |
19 | # Dependency overrides for the demo app, you would normally use this in dependencies:
20 | # flutter_floating_map_marker_titles_core: ^X.Y.Z+1
21 | # flutter_map_floating_marker_titles: ^X.Y.Z+1
22 | # google_maps_flutter_floating_marker_titles: ^X.Y.Z+1
23 | dependency_overrides:
24 | flutter_floating_map_marker_titles_core:
25 | path: ../flutter_floating_map_marker_titles_core
26 | flutter_map_floating_marker_titles:
27 | path: ../flutter_map_floating_marker_titles
28 | google_maps_flutter_floating_marker_titles:
29 | path: ../google_maps_flutter_floating_marker_titles
30 |
31 | dev_dependencies:
32 | flutter_test:
33 | sdk: flutter
34 | lint: 2.1.2
35 |
36 | flutter:
37 | uses-material-design: true
38 | assets:
39 | - lib/assets/images/marker.png
40 |
--------------------------------------------------------------------------------
/example/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility in the flutter_test package. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:flutter_floating_map_marker_titles_demo/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(DemoApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/example/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/web/favicon.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/example/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/example/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/example/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | flutter_floating_map_marker_titles_demo
33 |
34 |
35 |
39 |
40 |
41 |
42 |
43 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/example/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flutter_floating_map_marker_titles_demo",
3 | "short_name": "flutter_floating_map_marker_titles_demo",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/.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 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.1.1] - 2025/03/04
2 |
3 | * Fixed some warnings related to color class getters
4 |
5 | ## [1.1.0] - 2024/08/10
6 |
7 | * Fixed a bug with floating marker titles still appearing with maxTitlesCount=0 in some specific cases (e.g. using more than one z-index)
8 |
9 | ## [1.0.0] - 2023/06/22
10 |
11 | * Updated the semantic version prefix to "officially stable" 1.X.X, because this library has been successful in a production app (see https://mapmarker.app) used by thousands of daily users for several months
12 | * Updated latlong2 dependency to latlong2: ^0.9.0
13 |
14 | ## [0.3.0] - 2022/10/23
15 |
16 | * Improved the logic handling the appearance for higher z-index titles
17 |
18 | ## [0.2.0] - 2022/09/15
19 |
20 | * Added the ability to set floating marker titles with a stream with the `floatingTitlesStream` parameter
21 |
22 | ## [0.1.0] - 2022/09/02
23 |
24 | * Changed the versioning pattern to leave the last digit for minor non-feature-related changes (e.g. library upgrades)
25 |
26 | ## [0.0.6] - 2022/06/11
27 |
28 | Added linter rules from the [lint](https://pub.dev/packages/lint) package.
29 |
30 | ## [0.0.5+5] - 2022/01/09
31 |
32 | Removed web-specific code working around [a bug](https://github.com/flutter/flutter/issues/46683) that has since then been fixed.
33 |
34 | ## [0.0.4+4] - 2021/11/29
35 |
36 | Migrated to null safety.
37 |
38 | ## [0.0.3+3] - 2021/06/01
39 |
40 | Updated dependencies to support dependent libraries.
41 |
42 | ## [0.0.2+2] - 2021/04/01
43 |
44 | Fixed some issues with floating titles data not being updated in some cases, due to a wrong widget state setup.
45 |
46 | ## [0.0.1+1] - 2021/01/30
47 |
48 | This is the initial release of the library.
49 |
50 | * Floating Map Marker Titles
51 | * Titles overlap detection
52 | * Titles automatic outline based on color
53 | * Titles fade-in animation
54 | * Overlay customization options
55 | * Paint time interval
56 | * Text size
57 | * Text width
58 | * Text max lines
59 | * Text painting cache size
60 | * Coordinates cache size
61 | * Number of titles to check per frame
62 | * Fade-in animation time
63 | * Title placement policy
64 | * Title customization options
65 | * Color
66 | * Bold
67 | * Z-index
68 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, androidseb
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/README.md:
--------------------------------------------------------------------------------
1 | # Flutter Floating Map Marker Titles Core
2 |
3 | This is the core library for the [Flutter Floating Map Marker Titles](https://github.com/androidseb/flutter_map_floating_marker_titles) project.
4 |
5 | This core library is meant to be agnostic of any specific map view implementation details, so that it can be re-used with various map providers.
6 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:lint/analysis_options.yaml
2 |
3 | analyzer:
4 | exclude:
5 | - 'lib/utils/geo/bounds.dart'
6 | - 'lib/utils/geo/crs.dart'
7 | - 'lib/utils/geo/point.dart'
8 | # can be found at https://dart-lang.github.io/linter/lints/options/options.html
9 | linter:
10 | rules:
11 | avoid_positional_boolean_parameters: false
12 | avoid_classes_with_only_static_members: false
13 | use_setters_to_change_properties: false
14 | avoid_final_parameters: false
15 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/cache/epsg_3857_proj_cache.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math' as math;
2 | import 'package:flutter_floating_map_marker_titles_core/utils/cached_calculator.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/utils/geo/crs.dart';
4 | import 'package:latlong2/latlong.dart';
5 |
6 | class _Epsg3857ProjCacheKey {
7 | final LatLng latLng;
8 | final double zoom;
9 |
10 | _Epsg3857ProjCacheKey(
11 | this.latLng,
12 | this.zoom,
13 | );
14 |
15 | @override
16 | int get hashCode {
17 | return latLng.hashCode + zoom.hashCode;
18 | }
19 |
20 | @override
21 | bool operator ==(Object other) {
22 | if (other is! _Epsg3857ProjCacheKey) {
23 | return false;
24 | }
25 | final _Epsg3857ProjCacheKey o = other;
26 | return latLng == o.latLng && zoom == o.zoom;
27 | }
28 | }
29 |
30 | class _Epsg3857ProjCacheImpl extends CachedCalculator<_Epsg3857ProjCacheKey, math.Point> {
31 | static const Epsg3857 mapProjection = Epsg3857();
32 |
33 | _Epsg3857ProjCacheImpl(super.cacheMaxSize);
34 |
35 | @override
36 | math.Point calculateValue(final _Epsg3857ProjCacheKey key) {
37 | return mapProjection.latLngToPoint(key.latLng, key.zoom);
38 | }
39 | }
40 |
41 | class Epsg3857ProjCache {
42 | late _Epsg3857ProjCacheImpl _projectionsCache;
43 |
44 | Epsg3857ProjCache(final int cacheMaxSize) {
45 | _projectionsCache = _Epsg3857ProjCacheImpl(cacheMaxSize);
46 | }
47 |
48 | void updateFrom(final Epsg3857ProjCache projCache) {
49 | _projectionsCache = projCache._projectionsCache;
50 | }
51 |
52 | math.Point getProjectedLatLng(final LatLng latLng, final double zoom) {
53 | return _projectionsCache.getValue(_Epsg3857ProjCacheKey(latLng, zoom));
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/cache/text_painting_cache.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/display/floating_title_painter.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
4 | import 'package:flutter_floating_map_marker_titles_core/utils/cached_calculator.dart';
5 |
6 | class _TextPaintingCacheKey {
7 | final String textString;
8 | final Color textColor;
9 | final bool isBoldText;
10 | final FMTOOptions options;
11 |
12 | _TextPaintingCacheKey(
13 | this.textString,
14 | this.textColor,
15 | this.isBoldText,
16 | this.options,
17 | );
18 |
19 | @override
20 | int get hashCode {
21 | return textString.hashCode +
22 | textColor.hashCode +
23 | isBoldText.hashCode +
24 | options.maxTitleLines.hashCode +
25 | options.maxTitlesWidth.hashCode +
26 | options.textSize.hashCode;
27 | }
28 |
29 | @override
30 | bool operator ==(Object other) {
31 | if (other is! _TextPaintingCacheKey) {
32 | return false;
33 | }
34 | final _TextPaintingCacheKey o = other;
35 | return textString == o.textString &&
36 | textColor == o.textColor &&
37 | isBoldText == o.isBoldText &&
38 | options.maxTitleLines == o.options.maxTitleLines &&
39 | options.maxTitlesWidth == o.options.maxTitlesWidth &&
40 | options.textSize == o.options.textSize;
41 | }
42 | }
43 |
44 | class _TextPaintingCacheImpl extends CachedCalculator<_TextPaintingCacheKey, FloatingTitlePainter> {
45 | _TextPaintingCacheImpl(super.cacheMaxSize);
46 |
47 | @override
48 | FloatingTitlePainter calculateValue(final _TextPaintingCacheKey key) {
49 | return FloatingTitlePainter(
50 | key.textString,
51 | key.textColor,
52 | key.isBoldText,
53 | key.options,
54 | );
55 | }
56 | }
57 |
58 | class TextPaintingCache {
59 | late _TextPaintingCacheImpl _paintersCache;
60 |
61 | TextPaintingCache(final int cacheMaxSize) {
62 | _paintersCache = _TextPaintingCacheImpl(cacheMaxSize);
63 | }
64 |
65 | void updateFrom(final TextPaintingCache textPaintingCache) {
66 | _paintersCache = textPaintingCache._paintersCache;
67 | }
68 |
69 | FloatingTitlePainter getTitlePainter(
70 | final String textString,
71 | final Color textColor,
72 | final bool isBoldText,
73 | final FMTOOptions options,
74 | ) {
75 | return _paintersCache.getValue(
76 | _TextPaintingCacheKey(
77 | textString,
78 | textColor,
79 | isBoldText,
80 | options,
81 | ),
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/display/floating_title_painter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/display/layer/title_layer_background_painter.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/controller/display/layer/title_layer_foreground_painter.dart';
4 | import 'package:flutter_floating_map_marker_titles_core/controller/display/layer/title_layer_painter.dart';
5 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
6 |
7 | class FloatingTitlePainter {
8 | final TitleLayerPainter? _bgLayerPainter;
9 | final TitleLayerPainter _fgLayerPainter;
10 |
11 | factory FloatingTitlePainter(
12 | final String textString,
13 | final Color textColor,
14 | final bool isBoldText,
15 | final FMTOOptions fmtoOptions,
16 | ) {
17 | return FloatingTitlePainter._internal(
18 | _createBGPainter(textString, textColor, isBoldText, fmtoOptions),
19 | _createFGPainter(textString, textColor, isBoldText, fmtoOptions),
20 | );
21 | }
22 |
23 | FloatingTitlePainter._internal(
24 | this._bgLayerPainter,
25 | this._fgLayerPainter,
26 | );
27 |
28 | static TitleLayerPainter? _createBGPainter(
29 | final String textString,
30 | final Color textColor,
31 | final bool isBoldText,
32 | final FMTOOptions fmtoOptions,
33 | ) {
34 | return TitleLayerBackgroundPainter(
35 | textString,
36 | textColor,
37 | isBoldText,
38 | fmtoOptions,
39 | );
40 | }
41 |
42 | static TitleLayerPainter _createFGPainter(
43 | final String textString,
44 | final Color textColor,
45 | final bool isBoldText,
46 | final FMTOOptions fmtoOptions,
47 | ) {
48 | return TitleLayerForegroundPainter(
49 | textString,
50 | textColor,
51 | isBoldText,
52 | fmtoOptions,
53 | );
54 | }
55 |
56 | void paintTitle(final Canvas canvas, final Offset offset) {
57 | _bgLayerPainter?.paintLayer(canvas, offset);
58 | _fgLayerPainter.paintLayer(canvas, offset);
59 | }
60 |
61 | double get width {
62 | return _fgLayerPainter.width;
63 | }
64 |
65 | double get height {
66 | return _fgLayerPainter.height;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/display/layer/title_layer_background_painter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/display/layer/title_layer_painter.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
4 |
5 | class TitleLayerBackgroundPainter extends TitleLayerPainter {
6 | TitleLayerBackgroundPainter(
7 | super.textString,
8 | super.textColor,
9 | super.isBoldText,
10 | super.fmtoOptions,
11 | );
12 |
13 | @override
14 | TextSpan buildText(
15 | final String textString,
16 | final Color textColor,
17 | final bool isBoldText,
18 | final FMTOOptions fmtoOptions,
19 | ) {
20 | return TextSpan(
21 | style: TextStyle(
22 | fontSize: fmtoOptions.textSize,
23 | fontWeight: isBoldText ? FontWeight.bold : FontWeight.normal,
24 | foreground: Paint()
25 | ..style = PaintingStyle.stroke
26 | ..strokeWidth = 3
27 | ..color = TitleLayerPainter.computeBgColorForTextColor(textColor),
28 | ),
29 | text: textString,
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/display/layer/title_layer_foreground_painter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/display/layer/title_layer_painter.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
4 |
5 | class TitleLayerForegroundPainter extends TitleLayerPainter {
6 | TitleLayerForegroundPainter(
7 | super.textString,
8 | super.textColor,
9 | super.isBoldText,
10 | super.fmtoOptions,
11 | );
12 |
13 | @override
14 | TextSpan buildText(
15 | final String textString,
16 | final Color textColor,
17 | final bool isBoldText,
18 | final FMTOOptions fmtoOptions,
19 | ) {
20 | return TextSpan(
21 | style: TextStyle(
22 | fontSize: fmtoOptions.textSize,
23 | color: textColor,
24 | fontWeight: isBoldText ? FontWeight.bold : FontWeight.normal,
25 | ),
26 | text: textString,
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/display/layer/title_layer_painter.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/utils/utils.dart';
4 |
5 | abstract class TitleLayerPainter {
6 | static Color computeBgColorForTextColor(final Color textColor) {
7 | if (Utils.isDarkColor(textColor)) {
8 | return Colors.white;
9 | } else {
10 | return Colors.black;
11 | }
12 | }
13 |
14 | final String _textString;
15 | final Color _textColor;
16 | final bool _isBoldText;
17 | final FMTOOptions _fmtoOptions;
18 |
19 | late TextPainter _textPainter;
20 |
21 | TitleLayerPainter(
22 | this._textString,
23 | this._textColor,
24 | this._isBoldText,
25 | this._fmtoOptions,
26 | ) {
27 | _textPainter = _buildTextPainter();
28 | }
29 |
30 | TextSpan buildText(
31 | final String textString,
32 | final Color textColor,
33 | final bool isBoldText,
34 | final FMTOOptions fmtoOptions,
35 | );
36 |
37 | TextPainter _buildTextPainter() {
38 | final TextPainter textPainter = TextPainter(
39 | text: buildText(
40 | _textString,
41 | _textColor,
42 | _isBoldText,
43 | _fmtoOptions,
44 | ),
45 | textAlign: TextAlign.left,
46 | textDirection: TextDirection.ltr,
47 | maxLines: _fmtoOptions.maxTitleLines,
48 | ellipsis: '...',
49 | );
50 | textPainter.layout(maxWidth: _fmtoOptions.maxTitlesWidth);
51 | return textPainter;
52 | }
53 |
54 | double get width => _textPainter.width;
55 |
56 | double get height => _textPainter.height;
57 |
58 | void paintLayer(
59 | final Canvas canvas,
60 | final Offset offset,
61 | ) {
62 | _textPainter.paint(canvas, offset);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/display/titles_display_state.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/display/floating_title_painter.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/model/floating_marker_title_info.dart';
4 | import 'package:flutter_floating_map_marker_titles_core/utils/geo/bounds.dart';
5 | import 'package:flutter_floating_map_marker_titles_core/utils/geo/point.dart';
6 | import 'package:flutter_floating_map_marker_titles_core/utils/utils.dart';
7 |
8 | class TitleDisplayInfo {
9 | int creationTime;
10 | final FloatingMarkerTitleInfo floatingMarkerTitleInfo;
11 | final FloatingTitlePainter titlePainter;
12 | final Offset viewCoordinates;
13 | final Bounds _displayBounds;
14 |
15 | TitleDisplayInfo(
16 | this.floatingMarkerTitleInfo,
17 | this.titlePainter,
18 | this.viewCoordinates,
19 | ) : creationTime = Utils.currentTimeEpochMillis(),
20 | _displayBounds = Bounds(
21 | CustomPoint(
22 | viewCoordinates.dx,
23 | viewCoordinates.dy,
24 | ),
25 | CustomPoint(
26 | viewCoordinates.dx + titlePainter.width,
27 | viewCoordinates.dy + titlePainter.height,
28 | ),
29 | );
30 |
31 | bool intersectsWith(final TitleDisplayInfo titleDisplayInfo) {
32 | return _displayBounds.containsPartialBounds(titleDisplayInfo._displayBounds);
33 | }
34 | }
35 |
36 | class TitlesDisplayState {
37 | final Map _titleDisplayInfoMap = {};
38 | final Set fullyVisibleTitleIds = {};
39 | final Set fadingInTitleIds = {};
40 | final Set pendingFadeInTitleIds = {};
41 | int currentTitleIndex = 0;
42 | int lastFadeInStartTimeEpochMillis = 0;
43 |
44 | TitleDisplayInfo? getTitleDisplayInfo(final int floatingMarkerTitleInfoId) {
45 | return _titleDisplayInfoMap[floatingMarkerTitleInfoId];
46 | }
47 |
48 | void updateFrom(final TitlesDisplayState oldState) {
49 | _titleDisplayInfoMap.addAll(oldState._titleDisplayInfoMap);
50 | fullyVisibleTitleIds.addAll(oldState.fullyVisibleTitleIds);
51 | fadingInTitleIds.addAll(oldState.fadingInTitleIds);
52 | pendingFadeInTitleIds.addAll(oldState.pendingFadeInTitleIds);
53 | currentTitleIndex = oldState.currentTitleIndex;
54 | lastFadeInStartTimeEpochMillis = oldState.lastFadeInStartTimeEpochMillis;
55 | }
56 |
57 | void removeObsoleteTitles(final Iterable availableIds) {
58 | final Iterable currentIds = List.from(_titleDisplayInfoMap.keys);
59 | for (final currentId in currentIds) {
60 | if (!availableIds.contains(currentId)) {
61 | removeTitleInfo(currentId);
62 | }
63 | }
64 | }
65 |
66 | void removeAllTitles() {
67 | final Iterable currentIds = List.from(_titleDisplayInfoMap.keys);
68 | for (final currentId in currentIds) {
69 | removeTitleInfo(currentId);
70 | }
71 | }
72 |
73 | void removeTitleInfo(final int floatingMarkerTitleInfoId) {
74 | _titleDisplayInfoMap.remove(floatingMarkerTitleInfoId);
75 | fullyVisibleTitleIds.remove(floatingMarkerTitleInfoId);
76 | fadingInTitleIds.remove(floatingMarkerTitleInfoId);
77 | pendingFadeInTitleIds.remove(floatingMarkerTitleInfoId);
78 | }
79 |
80 | void updateWithTitleInfo(final TitleDisplayInfo titleDisplayInfo) {
81 | final TitleDisplayInfo? existingTDI = _titleDisplayInfoMap[titleDisplayInfo.floatingMarkerTitleInfo.id];
82 | if (existingTDI == null) {
83 | pendingFadeInTitleIds.add(titleDisplayInfo.floatingMarkerTitleInfo.id);
84 | } else {
85 | titleDisplayInfo.creationTime = existingTDI.creationTime;
86 | }
87 | _titleDisplayInfoMap[titleDisplayInfo.floatingMarkerTitleInfo.id] = titleDisplayInfo;
88 | }
89 |
90 | Iterable get titleDisplayInfos {
91 | return _titleDisplayInfoMap.values;
92 | }
93 |
94 | int get titlesCount {
95 | return _titleDisplayInfoMap.length;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/map_view_interface/abstract_czr_map_view_interface.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math' as math;
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/controller/cache/epsg_3857_proj_cache.dart';
4 | import 'package:flutter_floating_map_marker_titles_core/controller/map_view_interface/abstract_map_view_interface.dart';
5 | import 'package:latlong2/latlong.dart';
6 | import 'package:vector_math/vector_math.dart' as vector_math;
7 |
8 | abstract class AbstractCZRMapViewInterface extends AbstractMapViewInterface {
9 | final Epsg3857ProjCache _projCache;
10 |
11 | AbstractCZRMapViewInterface(final int projCacheSize) : _projCache = Epsg3857ProjCache(projCacheSize);
12 |
13 | @override
14 | void updateFrom(AbstractMapViewInterface oldMapInterface) {
15 | final AbstractCZRMapViewInterface oldMapInterfaceCast = oldMapInterface as AbstractCZRMapViewInterface;
16 | _projCache.updateFrom(oldMapInterfaceCast._projCache);
17 | }
18 |
19 | LatLng getMapViewCenter();
20 | double getMapViewZoom();
21 | double getMapViewRotationDegrees();
22 |
23 | @override
24 | Offset latLngToViewCoordinates(final LatLng latLng, final Size viewSize) {
25 | final LatLng centerLatLng = getMapViewCenter();
26 | final double mapViewZoom = getMapViewZoom();
27 | final double mapViewRotationDegrees = getMapViewRotationDegrees();
28 | final math.Point targetPoint = _projCache.getProjectedLatLng(latLng, mapViewZoom);
29 | final math.Point centerPoint = _projCache.getProjectedLatLng(centerLatLng, mapViewZoom);
30 | final double xDiff = targetPoint.x - (centerPoint.x as double);
31 | final double yDiff = targetPoint.y - (centerPoint.y as double);
32 | final double viewCenterX = viewSize.width / 2;
33 | final double viewCenterY = viewSize.height / 2;
34 | if (mapViewRotationDegrees == 0) {
35 | return Offset(viewCenterX + xDiff, viewCenterY + yDiff);
36 | } else {
37 | final double radius = math.sqrt(math.pow(xDiff, 2) + math.pow(yDiff, 2));
38 | final double baseAngleRad = math.acos(xDiff / radius);
39 | final double angleDeltaRad = vector_math.radians(mapViewRotationDegrees);
40 | double resultingAngleRad;
41 | if (yDiff >= 0) {
42 | resultingAngleRad = baseAngleRad + angleDeltaRad;
43 | } else {
44 | resultingAngleRad = angleDeltaRad - baseAngleRad;
45 | }
46 | final double translatedXDiff = radius * math.cos(resultingAngleRad);
47 | final double translatedYDiff = radius * math.sin(resultingAngleRad);
48 | return Offset(
49 | viewCenterX + translatedXDiff,
50 | viewCenterY + translatedYDiff,
51 | );
52 | }
53 | }
54 |
55 | @override
56 | String getMapViewTitlesPerspectiveValue() {
57 | return '${getMapViewRotationDegrees()}-${getMapViewZoom()}';
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/controller/map_view_interface/abstract_map_view_interface.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:latlong2/latlong.dart';
3 |
4 | abstract class AbstractMapViewInterface {
5 | /// Update the Map Interface from a previous instance.
6 | /// This method is the ideal moment to transfer any cache data from the old instance
7 | void updateFrom(final AbstractMapViewInterface oldMapInterface);
8 |
9 | /// Convert LatLng coordinates to screen coordinates
10 | Offset latLngToViewCoordinates(final LatLng latLng, final Size viewSize);
11 |
12 | /// Return the current Map View Titles Perspective Value:
13 | /// This value is a way to identify when the map view perspective has changed in a way
14 | /// floating titles might collide with each other (e.g. zoom, rotation, tilt, etc.)
15 | /// This allows the floating titles controller to know when to ignore existing titles collisions,
16 | /// to avoid making titles blink when they are too close together with coordinates calculations
17 | /// rounding makes them look like they are colliding/not colliding every other frame.
18 | String getMapViewTitlesPerspectiveValue() ;
19 | }
20 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/model/floating_marker_title_info.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:latlong2/latlong.dart';
3 |
4 | class FloatingMarkerTitleInfo {
5 | /// ID of the floating title, used by the system to track what was added/removed between two paints
6 | final int id;
7 |
8 | /// Base coordinates the title is attached to
9 | final LatLng latLng;
10 |
11 | /// The title text as a String
12 | final String title;
13 |
14 | /// The title base color
15 | final Color color;
16 |
17 | /// Whether the title text should be written in bold
18 | final bool isBold;
19 |
20 | /// z-index of the title to specify which title has the most priority for display in case of titles collisions
21 | final int zIndex;
22 |
23 | FloatingMarkerTitleInfo({
24 | required this.id,
25 | required this.latLng,
26 | required this.title,
27 | required this.color,
28 | this.isBold = false,
29 | this.zIndex = 1,
30 | });
31 | }
32 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/utils/cached_calculator.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_floating_map_marker_titles_core/utils/rotating_cache.dart';
2 |
3 | abstract class CachedCalculator {
4 | final RotatingCache _cache;
5 |
6 | static int _computeSaneHalfCacheSize(final int cacheMaxSize) {
7 | if (cacheMaxSize < 2) {
8 | return 1;
9 | } else {
10 | return (cacheMaxSize / 2).floor();
11 | }
12 | }
13 |
14 | CachedCalculator(final int cacheMaxSize) : _cache = RotatingCache(_computeSaneHalfCacheSize(cacheMaxSize));
15 |
16 | V getValue(final K key) {
17 | final V? existingCacheEntry = _cache.getValue(key);
18 | if (existingCacheEntry != null) {
19 | return existingCacheEntry;
20 | }
21 | final V createdCacheEntry = calculateValue(key);
22 | _cache.putValue(key, createdCacheEntry);
23 | return createdCacheEntry;
24 | }
25 |
26 | V calculateValue(final K key);
27 | }
28 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/utils/geo/bounds.dart:
--------------------------------------------------------------------------------
1 | // File copied from the flutter_map project to re-use projection utils classes
2 | // Source project file: https://raw.githubusercontent.com/fleaflet/flutter_map/master/lib/src/core/bounds.dart
3 |
4 | import 'dart:math' as math;
5 |
6 | import 'package:flutter_floating_map_marker_titles_core/utils/geo/point.dart';
7 |
8 | /// Rectangular bound delimited by orthogonal lines passing through two
9 | /// points.
10 | class Bounds {
11 | final CustomPoint min;
12 | final CustomPoint max;
13 |
14 | factory Bounds(CustomPoint a, CustomPoint b) {
15 | var bounds1 = Bounds._(a, b);
16 | var bounds2 = bounds1.extend(a);
17 | return bounds2.extend(b);
18 | }
19 |
20 | const Bounds._(this.min, this.max);
21 |
22 | /// Creates a new [Bounds] obtained by expanding the current ones with a new
23 | /// point.
24 | Bounds extend(CustomPoint point) {
25 | return Bounds._(
26 | CustomPoint(
27 | math.min(point.x, min.x),
28 | math.min(point.y, min.y),
29 | ),
30 | CustomPoint(
31 | math.max(point.x, max.x),
32 | math.max(point.y, max.y),
33 | ),
34 | );
35 | }
36 |
37 | /// This [Bounds] central point.
38 | CustomPoint get center => CustomPoint(
39 | (min.x + max.x) / 2,
40 | (min.y + max.y) / 2,
41 | );
42 |
43 | /// Bottom-Left corner's point.
44 | CustomPoint get bottomLeft => CustomPoint(min.x, max.y);
45 |
46 | /// Top-Right corner's point.
47 | CustomPoint get topRight => CustomPoint(max.x, min.y);
48 |
49 | /// Top-Left corner's point.
50 | CustomPoint get topLeft => min;
51 |
52 | /// Bottom-Right corner's point.
53 | CustomPoint get bottomRight => max;
54 |
55 | /// A point that contains the difference between the point's axis projections.
56 | CustomPoint get size {
57 | return max - min;
58 | }
59 |
60 | bool contains(CustomPoint point) {
61 | var min = point;
62 | var max = point;
63 | return containsBounds(Bounds(min, max));
64 | }
65 |
66 | bool containsBounds(Bounds b) {
67 | return (b.min.x >= min.x) &&
68 | (b.max.x <= max.x) &&
69 | (b.min.y >= min.y) &&
70 | (b.max.y <= max.y);
71 | }
72 |
73 | bool containsPartialBounds(Bounds b) {
74 | return (b.min.x <= max.x) &&
75 | (b.max.x >= min.x) &&
76 | (b.min.y <= max.y) &&
77 | (b.max.y >= min.y);
78 | }
79 |
80 | @override
81 | String toString() => 'Bounds($min, $max)';
82 | }
83 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/utils/geo/crs.dart:
--------------------------------------------------------------------------------
1 | // File copied from the flutter_map project to re-use projection utils classes
2 | // Source project file: https://raw.githubusercontent.com/fleaflet/flutter_map/master/lib/src/geo/crs/crs.dart
3 |
4 | import 'dart:math' as math;
5 |
6 | import 'package:flutter_floating_map_marker_titles_core/utils/geo/bounds.dart';
7 | import 'package:flutter_floating_map_marker_titles_core/utils/geo/point.dart';
8 | import 'package:latlong2/latlong.dart';
9 | import 'package:meta/meta.dart';
10 | import 'package:proj4dart/proj4dart.dart' as proj4;
11 | import 'package:tuple/tuple.dart';
12 |
13 | /// An abstract representation of a
14 | /// [Coordinate Reference System](https://bit.ly/3iVKpja).
15 | ///
16 | /// The main objective of a CRS is to handle the conversion between surface
17 | /// points of objects of different dimensions. In our case 3D and 2D objects.
18 | abstract class Crs {
19 | String get code;
20 |
21 | Projection get projection;
22 |
23 | Transformation get transformation;
24 |
25 | const Crs();
26 |
27 | /// Converts a point on the sphere surface (with a certain zoom) in a
28 | /// map point.
29 | CustomPoint latLngToPoint(LatLng latlng, double zoom) {
30 | try {
31 | var projectedPoint = projection.project(latlng);
32 | var scale = this.scale(zoom);
33 | return transformation.transform(projectedPoint, scale.toDouble());
34 | } catch (e) {
35 | return CustomPoint(0.0, 0.0);
36 | }
37 | }
38 |
39 | /// Converts a map point to the sphere coordinate (at a certain zoom).
40 | LatLng? pointToLatLng(CustomPoint point, double zoom) {
41 | var scale = this.scale(zoom);
42 | var untransformedPoint =
43 | transformation.untransform(point, scale.toDouble());
44 | try {
45 | return projection.unproject(untransformedPoint);
46 | } catch (e) {
47 | return null;
48 | }
49 | }
50 |
51 | /// Zoom to Scale function.
52 | num scale(double zoom) {
53 | return 256 * math.pow(2, zoom);
54 | }
55 |
56 | /// Scale to Zoom function.
57 | num zoom(double scale) {
58 | return math.log(scale / 256) / math.ln2;
59 | }
60 |
61 | /// Rescales the bounds to a given zoom value.
62 | Bounds? getProjectedBounds(double zoom) {
63 | if (infinite) return null;
64 |
65 | var b = projection.bounds!;
66 | var s = scale(zoom);
67 | var min = transformation.transform(b.min, s.toDouble());
68 | var max = transformation.transform(b.max, s.toDouble());
69 | return Bounds(min, max);
70 | }
71 |
72 | bool get infinite;
73 |
74 | Tuple2? get wrapLng;
75 |
76 | Tuple2? get wrapLat;
77 | }
78 |
79 | // Custom CRS for non geographical maps
80 | class CrsSimple extends Crs {
81 | @override
82 | final String code = 'CRS.SIMPLE';
83 |
84 | @override
85 | final Projection projection;
86 |
87 | @override
88 | final Transformation transformation;
89 |
90 | CrsSimple()
91 | : projection = const _LonLat(),
92 | transformation = Transformation(1, 0, -1, 0),
93 | super();
94 |
95 | @override
96 | bool get infinite => false;
97 |
98 | @override
99 | Tuple2? get wrapLat => null;
100 |
101 | @override
102 | Tuple2? get wrapLng => null;
103 | }
104 |
105 | abstract class Earth extends Crs {
106 | @override
107 | bool get infinite => false;
108 |
109 | @override
110 | final Tuple2 wrapLng = const Tuple2(-180.0, 180.0);
111 |
112 | @override
113 | final Tuple2? wrapLat = null;
114 |
115 | const Earth() : super();
116 | }
117 |
118 | /// The most common CRS used for rendering maps.
119 | class Epsg3857 extends Earth {
120 | @override
121 | final String code = 'EPSG:3857';
122 |
123 | @override
124 | final Projection projection;
125 |
126 | @override
127 | final Transformation transformation;
128 |
129 | static const num _scale = 0.5 / (math.pi * SphericalMercator.r);
130 |
131 | const Epsg3857()
132 | : projection = const SphericalMercator(),
133 | transformation = const Transformation(_scale, 0.5, -_scale, 0.5),
134 | super();
135 |
136 | //@override
137 | //Tuple2 get wrapLat => const Tuple2(-85.06, 85.06);
138 | }
139 |
140 | /// A common CRS among GIS enthusiasts. Uses simple Equirectangular projection.
141 | class Epsg4326 extends Earth {
142 | @override
143 | final String code = 'EPSG:4326';
144 |
145 | @override
146 | final Projection projection;
147 |
148 | @override
149 | final Transformation transformation;
150 |
151 | const Epsg4326()
152 | : projection = const _LonLat(),
153 | transformation = const Transformation(1 / 180, 0.5, -1 / 180, 0.5),
154 | super();
155 | }
156 |
157 | /// Custom CRS
158 | class Proj4Crs extends Crs {
159 | @override
160 | final String code;
161 |
162 | @override
163 | final Projection projection;
164 |
165 | @override
166 | final Transformation transformation;
167 |
168 | @override
169 | final bool infinite;
170 |
171 | @override
172 | final Tuple2? wrapLat = null;
173 |
174 | @override
175 | final Tuple2? wrapLng = null;
176 |
177 | final List? _transformations;
178 |
179 | final List _scales;
180 |
181 | Proj4Crs._({
182 | required this.code,
183 | required this.projection,
184 | required this.transformation,
185 | required this.infinite,
186 | List? transformations,
187 | required List scales,
188 | }) : _transformations = transformations,
189 | _scales = scales;
190 |
191 | factory Proj4Crs.fromFactory({
192 | required String code,
193 | required proj4.Projection proj4Projection,
194 | Transformation? transformation,
195 | List? origins,
196 | Bounds? bounds,
197 | List? scales,
198 | List? resolutions,
199 | }) {
200 | final projection =
201 | _Proj4Projection(proj4Projection: proj4Projection, bounds: bounds);
202 | List? transformations;
203 | var infinite = null == bounds;
204 | List finalScales;
205 |
206 | if (null != scales && scales.isNotEmpty) {
207 | finalScales = scales;
208 | } else if (null != resolutions && resolutions.isNotEmpty) {
209 | finalScales = resolutions.map((r) => 1 / r).toList(growable: false);
210 | } else {
211 | throw Exception(
212 | 'Please provide scales or resolutions to determine scales');
213 | }
214 |
215 | if (null == origins || origins.isEmpty) {
216 | transformation ??= Transformation(1, 0, -1, 0);
217 | } else {
218 | if (origins.length == 1) {
219 | var origin = origins[0];
220 | transformation = Transformation(1, -origin.x, -1, origin.y);
221 | } else {
222 | transformations =
223 | origins.map((p) => Transformation(1, -p.x, -1, p.y)).toList();
224 | transformation = null;
225 | }
226 | }
227 |
228 | return Proj4Crs._(
229 | code: code,
230 | projection: projection,
231 | transformation: transformation!,
232 | infinite: infinite,
233 | transformations: transformations,
234 | scales: finalScales,
235 | );
236 | }
237 |
238 | /// Converts a point on the sphere surface (with a certain zoom) in a
239 | /// map point.
240 | @override
241 | CustomPoint latLngToPoint(LatLng latlng, double zoom) {
242 | try {
243 | var projectedPoint = projection.project(latlng);
244 | var scale = this.scale(zoom);
245 | var transformation = _getTransformationByZoom(zoom);
246 |
247 | return transformation.transform(projectedPoint, scale.toDouble());
248 | } catch (e) {
249 | return CustomPoint(0.0, 0.0);
250 | }
251 | }
252 |
253 | /// Converts a map point to the sphere coordinate (at a certain zoom).
254 | @override
255 | LatLng? pointToLatLng(CustomPoint point, double zoom) {
256 | var scale = this.scale(zoom);
257 | var transformation = _getTransformationByZoom(zoom);
258 |
259 | var untransformedPoint =
260 | transformation.untransform(point, scale.toDouble());
261 | try {
262 | return projection.unproject(untransformedPoint);
263 | } catch (e) {
264 | return null;
265 | }
266 | }
267 |
268 | /// Rescales the bounds to a given zoom value.
269 | @override
270 | Bounds? getProjectedBounds(double zoom) {
271 | if (infinite) return null;
272 |
273 | var b = projection.bounds!;
274 | var s = scale(zoom);
275 |
276 | var transformation = _getTransformationByZoom(zoom);
277 |
278 | var min = transformation.transform(b.min, s.toDouble());
279 | var max = transformation.transform(b.max, s.toDouble());
280 | return Bounds(min, max);
281 | }
282 |
283 | /// Zoom to Scale function.
284 | @override
285 | num scale(double zoom) {
286 | var iZoom = zoom.floor();
287 | if (zoom == iZoom) {
288 | return _scales[iZoom];
289 | } else {
290 | // Non-integer zoom, interpolate
291 | var baseScale = _scales[iZoom];
292 | var nextScale = _scales[iZoom + 1];
293 | var scaleDiff = nextScale - baseScale;
294 | var zDiff = (zoom - iZoom);
295 | return baseScale + scaleDiff * zDiff;
296 | }
297 | }
298 |
299 | /// Scale to Zoom function.
300 | @override
301 | num zoom(double scale) {
302 | // Find closest number in _scales, down
303 | var downScale = _closestElement(_scales, scale);
304 | if (downScale == null) {
305 | return double.negativeInfinity;
306 | }
307 | var downZoom = _scales.indexOf(downScale);
308 | // Check if scale is downScale => return array index
309 | if (scale == downScale) {
310 | return downZoom;
311 | }
312 | // Interpolate
313 | var nextZoom = downZoom + 1;
314 | var nextScale = _scales[nextZoom];
315 |
316 | var scaleDiff = nextScale - downScale;
317 | return (scale - downScale) / scaleDiff + downZoom;
318 | }
319 |
320 | /// Get the closest lowest element in an array
321 | double? _closestElement(List array, double element) {
322 | double? low;
323 | for (var i = array.length - 1; i >= 0; i--) {
324 | var curr = array[i];
325 |
326 | if (curr <= element && (null == low || low < curr)) {
327 | low = curr;
328 | }
329 | }
330 | return low;
331 | }
332 |
333 | /// returns Transformation object based on zoom
334 | Transformation _getTransformationByZoom(double zoom) {
335 | if (null == _transformations) {
336 | return transformation;
337 | }
338 |
339 | var iZoom = zoom.round();
340 | var lastIdx = _transformations!.length - 1;
341 |
342 | return _transformations![iZoom > lastIdx ? lastIdx : iZoom];
343 | }
344 | }
345 |
346 | abstract class Projection {
347 | const Projection();
348 |
349 | Bounds? get bounds;
350 |
351 | CustomPoint project(LatLng latlng);
352 |
353 | LatLng unproject(CustomPoint point);
354 |
355 | double _inclusive(Comparable start, Comparable end, double value) {
356 | if (value.compareTo(start as num) < 0) return start as double;
357 | if (value.compareTo(end as num) > 0) return end as double;
358 |
359 | return value;
360 | }
361 |
362 | @protected
363 | double inclusiveLat(double value) {
364 | return _inclusive(-90.0, 90.0, value);
365 | }
366 |
367 | @protected
368 | double inclusiveLng(double value) {
369 | return _inclusive(-180.0, 180.0, value);
370 | }
371 | }
372 |
373 | class _LonLat extends Projection {
374 | static final Bounds _bounds = Bounds(
375 | CustomPoint(-180.0, -90.0), CustomPoint(180.0, 90.0));
376 |
377 | const _LonLat() : super();
378 |
379 | @override
380 | Bounds get bounds => _bounds;
381 |
382 | @override
383 | CustomPoint project(LatLng latlng) {
384 | return CustomPoint(latlng.longitude, latlng.latitude);
385 | }
386 |
387 | @override
388 | LatLng unproject(CustomPoint point) {
389 | return LatLng(
390 | inclusiveLat(point.y as double), inclusiveLng(point.x as double));
391 | }
392 | }
393 |
394 | class SphericalMercator extends Projection {
395 | static const int r = 6378137;
396 | static const double maxLatitude = 85.0511287798;
397 | static const double _boundsD = r * math.pi;
398 | static final Bounds _bounds = Bounds(
399 | CustomPoint(-_boundsD, -_boundsD),
400 | CustomPoint(_boundsD, _boundsD),
401 | );
402 |
403 | const SphericalMercator() : super();
404 |
405 | @override
406 | Bounds get bounds => _bounds;
407 |
408 | @override
409 | CustomPoint project(LatLng latlng) {
410 | var d = math.pi / 180;
411 | var max = maxLatitude;
412 | var lat = math.max(math.min(max, latlng.latitude), -max);
413 | var sin = math.sin(lat * d);
414 |
415 | return CustomPoint(
416 | r * latlng.longitude * d, r * math.log((1 + sin) / (1 - sin)) / 2);
417 | }
418 |
419 | @override
420 | LatLng unproject(CustomPoint point) {
421 | var d = 180 / math.pi;
422 | return LatLng(
423 | inclusiveLat(
424 | (2 * math.atan(math.exp(point.y / r)) - (math.pi / 2)) * d),
425 | inclusiveLng(point.x * d / r));
426 | }
427 | }
428 |
429 | class _Proj4Projection extends Projection {
430 | final proj4.Projection epsg4326;
431 |
432 | final proj4.Projection proj4Projection;
433 |
434 | @override
435 | final Bounds? bounds;
436 |
437 | _Proj4Projection({
438 | required this.proj4Projection,
439 | this.bounds,
440 | }) : epsg4326 = proj4.Projection.WGS84;
441 |
442 | @override
443 | CustomPoint project(LatLng latlng) {
444 | var point = epsg4326.transform(
445 | proj4Projection, proj4.Point(x: latlng.longitude, y: latlng.latitude));
446 |
447 | return CustomPoint(point.x, point.y);
448 | }
449 |
450 | @override
451 | LatLng unproject(CustomPoint point) {
452 | var point2 = proj4Projection.transform(
453 | epsg4326, proj4.Point(x: point.x as double, y: point.y as double));
454 |
455 | return LatLng(inclusiveLat(point2.y), inclusiveLng(point2.x));
456 | }
457 | }
458 |
459 | class Transformation {
460 | final num a;
461 | final num b;
462 | final num c;
463 | final num d;
464 |
465 | const Transformation(this.a, this.b, this.c, this.d);
466 |
467 | CustomPoint transform(CustomPoint point, double? scale) {
468 | scale ??= 1.0;
469 | var x = scale * (a * point.x + b);
470 | var y = scale * (c * point.y + d);
471 | return CustomPoint(x, y);
472 | }
473 |
474 | CustomPoint untransform(CustomPoint point, double? scale) {
475 | scale ??= 1.0;
476 | var x = (point.x / scale - b) / a;
477 | var y = (point.y / scale - d) / c;
478 | return CustomPoint(x, y);
479 | }
480 | }
481 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/utils/geo/point.dart:
--------------------------------------------------------------------------------
1 | // File copied from the flutter_map project to re-use projection utils classes
2 | // Source project file: https://github.com/fleaflet/flutter_map/blob/master/lib/src/core/point.dart
3 |
4 | import 'dart:math' as math;
5 |
6 | class CustomPoint extends math.Point {
7 | const CustomPoint(num x, num y) : super(x as T, y as T);
8 |
9 | CustomPoint operator /(num /*T|int*/ factor) {
10 | return CustomPoint(x / factor, y / factor);
11 | }
12 |
13 | CustomPoint ceil() {
14 | return CustomPoint(x.ceil(), y.ceil());
15 | }
16 |
17 | CustomPoint floor() {
18 | return CustomPoint(x.floor(), y.floor());
19 | }
20 |
21 | CustomPoint unscaleBy(CustomPoint point) {
22 | return CustomPoint(x / point.x, y / point.y);
23 | }
24 |
25 | @override
26 | CustomPoint operator +(math.Point other) {
27 | return CustomPoint(x + other.x, y + other.y);
28 | }
29 |
30 | @override
31 | CustomPoint operator -(math.Point other) {
32 | return CustomPoint(x - other.x, y - other.y);
33 | }
34 |
35 | @override
36 | CustomPoint operator *(num /*T|int*/ factor) {
37 | return CustomPoint((x * factor), (y * factor));
38 | }
39 |
40 | CustomPoint scaleBy(CustomPoint point) {
41 | return CustomPoint(x * point.x, y * point.y);
42 | }
43 |
44 | CustomPoint round() {
45 | final x = this.x is double ? this.x.round() : this.x;
46 | final y = this.y is double ? this.y.round() : this.y;
47 | return CustomPoint(x, y);
48 | }
49 |
50 | CustomPoint multiplyBy(num n) {
51 | return CustomPoint(x * n, y * n);
52 | }
53 |
54 | // Clockwise rotation
55 | CustomPoint rotate(num radians) {
56 | if (radians != 0.0) {
57 | final cos = math.cos(radians);
58 | final sin = math.sin(radians);
59 | final nx = (cos * x) + (sin * y);
60 | final ny = (cos * y) - (sin * x);
61 |
62 | return CustomPoint(nx, ny);
63 | }
64 |
65 | return this;
66 | }
67 |
68 | @override
69 | String toString() => 'CustomPoint ($x, $y)';
70 | }
71 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/utils/rotating_cache.dart:
--------------------------------------------------------------------------------
1 | class RotatingCache {
2 | final int halfCacheMaxSize;
3 |
4 | Map _primaryCache = {};
5 | Map _secondaryCache = {};
6 |
7 | RotatingCache(this.halfCacheMaxSize);
8 |
9 | void _swapCaches() {
10 | final Map tmp = _primaryCache;
11 | _primaryCache = _secondaryCache;
12 | _secondaryCache = tmp;
13 | }
14 |
15 | V? getValue(final K key) {
16 | V? cachedValue = _primaryCache[key];
17 | if (cachedValue != null) {
18 | return cachedValue;
19 | }
20 | cachedValue = _secondaryCache[key];
21 | if (cachedValue == null) {
22 | return null;
23 | }
24 |
25 | putValue(key, cachedValue);
26 | return cachedValue;
27 | }
28 |
29 | void putValue(final K key, final V value) {
30 | if (_primaryCache.length >= halfCacheMaxSize) {
31 | _secondaryCache.clear();
32 | _swapCaches();
33 | }
34 | _primaryCache[key] = value;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/utils/utils.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class Utils {
4 | static const double minLuminanceToLightTinting = 0.75;
5 |
6 | static double colorLuminance(final Color color) {
7 | final double red = color.r;
8 | final double green = color.g;
9 | final double blue = color.b;
10 |
11 | return 0.2126 * red + 0.7152 * green + 0.0722 * blue;
12 | }
13 |
14 | static bool isDarkColor(final Color color) {
15 | return colorLuminance(color) < minLuminanceToLightTinting;
16 | }
17 |
18 | static int currentTimeEpochMillis() {
19 | return DateTime.now().millisecondsSinceEpoch;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/view/abstract_map_view_wrapper.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/controller/map_view_interface/abstract_map_view_interface.dart';
4 | import 'package:flutter_floating_map_marker_titles_core/model/floating_marker_title_info.dart';
5 | import 'package:flutter_floating_map_marker_titles_core/view/floating_marker_titles_overlay.dart';
6 |
7 | abstract class AbstractMapViewWrapper extends StatelessWidget {
8 | final T _mapViewInterface;
9 | final FMTOOptions _fmtoOptions;
10 | final List? floatingTitles;
11 | final Stream>? floatingTitlesStream;
12 |
13 | const AbstractMapViewWrapper(
14 | this._mapViewInterface,
15 | this._fmtoOptions, {
16 | super.key,
17 | this.floatingTitles,
18 | this.floatingTitlesStream,
19 | });
20 |
21 | Widget buildMapView(final BuildContext context, final T mapViewInterface);
22 |
23 | @override
24 | Widget build(final BuildContext context) {
25 | return Stack(
26 | children: [
27 | buildMapView(context, _mapViewInterface),
28 | FlutterMapFloatingMarkerTitlesOverlay(
29 | _mapViewInterface,
30 | _fmtoOptions,
31 | floatingTitles: floatingTitles,
32 | floatingTitlesStream: floatingTitlesStream,
33 | ),
34 | ],
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/view/floating_marker_titles_overlay.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
3 | import 'package:flutter_floating_map_marker_titles_core/controller/map_view_interface/abstract_map_view_interface.dart';
4 | import 'package:flutter_floating_map_marker_titles_core/model/floating_marker_title_info.dart';
5 | import 'package:flutter_floating_map_marker_titles_core/view/floating_marker_titles_overlay_layer.dart';
6 |
7 | class FlutterMapFloatingMarkerTitlesOverlay extends StatefulWidget {
8 | final FMTOController _fmtoController;
9 |
10 | FlutterMapFloatingMarkerTitlesOverlay(
11 | final AbstractMapViewInterface mapViewInterface,
12 | final FMTOOptions fmtoOptions, {
13 | super.key,
14 | final List? floatingTitles,
15 | final Stream>? floatingTitlesStream,
16 | }) : _fmtoController = FMTOController(
17 | mapViewInterface,
18 | fmtoOptions,
19 | floatingTitles: floatingTitles,
20 | floatingTitlesStream: floatingTitlesStream,
21 | );
22 |
23 | @override
24 | _FlutterMapFloatingMarkerTitlesOverlayState createState() => _FlutterMapFloatingMarkerTitlesOverlayState();
25 | }
26 |
27 | class _FlutterMapFloatingMarkerTitlesOverlayState extends State {
28 | @override
29 | void didUpdateWidget(covariant FlutterMapFloatingMarkerTitlesOverlay oldWidget) {
30 | widget._fmtoController.updateFrom(oldWidget._fmtoController);
31 | super.didUpdateWidget(oldWidget);
32 | }
33 |
34 | @override
35 | Widget build(final BuildContext context) {
36 | return Stack(
37 | children: [
38 | FlutterMapFloatingMarkerTitlesOverlayLayer(
39 | widget._fmtoController,
40 | ),
41 | _FMTOTransparentTitlesLayerWrapper(widget._fmtoController),
42 | ],
43 | );
44 | }
45 | }
46 |
47 | class _FMTOTransparentTitlesLayerWrapper extends StatefulWidget {
48 | final FMTOController _fmtoController;
49 |
50 | const _FMTOTransparentTitlesLayerWrapper(
51 | this._fmtoController,
52 | );
53 |
54 | @override
55 | _FMTOTransparentTitlesLayerWrapperState createState() => _FMTOTransparentTitlesLayerWrapperState();
56 | }
57 |
58 | class _FMTOTransparentTitlesLayerWrapperState extends State<_FMTOTransparentTitlesLayerWrapper> {
59 | double _transparentTitlesOpacity = 0;
60 |
61 | @override
62 | Widget build(final BuildContext context) {
63 | widget._fmtoController.setOnTransparentTitlesOpacityChanged((final double transparentTitlesOpacity) {
64 | Future.delayed(Duration.zero, () {
65 | setState(() {
66 | _transparentTitlesOpacity = transparentTitlesOpacity;
67 | });
68 | });
69 | });
70 | return Opacity(
71 | opacity: _transparentTitlesOpacity,
72 | child: FlutterMapFloatingMarkerTitlesOverlayLayer(
73 | widget._fmtoController,
74 | transparentTitles: true,
75 | ),
76 | );
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/lib/view/floating_marker_titles_overlay_layer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/widgets.dart';
2 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
3 |
4 | class FlutterMapFloatingMarkerTitlesOverlayLayer extends StatelessWidget {
5 | final FMTOController _fmtoController;
6 | final bool transparentTitles;
7 | const FlutterMapFloatingMarkerTitlesOverlayLayer(
8 | this._fmtoController, {
9 | this.transparentTitles = false,
10 | });
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Container(
15 | constraints: const BoxConstraints.expand(),
16 | child: CustomPaint(
17 | foregroundPainter: _FloatingMarkersTitlesPainter(
18 | _fmtoController,
19 | _FMTPainterNotifier(),
20 | transparentTitles,
21 | ),
22 | ),
23 | );
24 | }
25 | }
26 |
27 | class _FMTPainterNotifier extends ChangeNotifier {
28 | void triggerRepaint() {
29 | notifyListeners();
30 | }
31 | }
32 |
33 | class _FloatingMarkersTitlesPainter extends CustomPainter {
34 | final _FMTPainterNotifier _changeNotifier;
35 | final FMTOController _fmtoController;
36 | final bool _transparentTitles;
37 |
38 | _FloatingMarkersTitlesPainter(
39 | this._fmtoController,
40 | final _FMTPainterNotifier changeNotifier,
41 | final bool transparentTitles,
42 | ) : _changeNotifier = changeNotifier,
43 | _transparentTitles = transparentTitles,
44 | super(repaint: changeNotifier) {
45 | if (!_transparentTitles) {
46 | _repaintForever();
47 | }
48 | }
49 |
50 | Future _repaintForever() async {
51 | while (true) {
52 | await Future.delayed(
53 | Duration(
54 | milliseconds: _fmtoController.fmtoOptions.repaintIntervalMillis,
55 | ),
56 | );
57 | _changeNotifier.triggerRepaint();
58 | }
59 | }
60 |
61 | @override
62 | void paint(final Canvas canvas, final Size size) {
63 | if (size.width > 0 && size.height > 0) {
64 | // This call to clipRect is necessary to make sure the drawing doesn't happen over other views
65 | canvas.clipRect(
66 | Rect.fromLTRB(
67 | 0,
68 | 0,
69 | size.width,
70 | size.height,
71 | ),
72 | );
73 | }
74 | _fmtoController.paintFloatingMarkerTitles(
75 | canvas,
76 | size,
77 | _transparentTitles,
78 | );
79 | }
80 |
81 | @override
82 | bool shouldRepaint(final CustomPainter oldDelegate) {
83 | return true;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.1"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.19.0"
44 | fake_async:
45 | dependency: transitive
46 | description:
47 | name: fake_async
48 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.3.1"
52 | flutter:
53 | dependency: "direct main"
54 | description: flutter
55 | source: sdk
56 | version: "0.0.0"
57 | flutter_test:
58 | dependency: "direct dev"
59 | description: flutter
60 | source: sdk
61 | version: "0.0.0"
62 | intl:
63 | dependency: transitive
64 | description:
65 | name: intl
66 | sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
67 | url: "https://pub.dev"
68 | source: hosted
69 | version: "0.17.0"
70 | latlong2:
71 | dependency: "direct main"
72 | description:
73 | name: latlong2
74 | sha256: "18712164760cee655bc790122b0fd8f3d5b3c36da2cb7bf94b68a197fbb0811b"
75 | url: "https://pub.dev"
76 | source: hosted
77 | version: "0.9.0"
78 | leak_tracker:
79 | dependency: transitive
80 | description:
81 | name: leak_tracker
82 | sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
83 | url: "https://pub.dev"
84 | source: hosted
85 | version: "10.0.7"
86 | leak_tracker_flutter_testing:
87 | dependency: transitive
88 | description:
89 | name: leak_tracker_flutter_testing
90 | sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
91 | url: "https://pub.dev"
92 | source: hosted
93 | version: "3.0.8"
94 | leak_tracker_testing:
95 | dependency: transitive
96 | description:
97 | name: leak_tracker_testing
98 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
99 | url: "https://pub.dev"
100 | source: hosted
101 | version: "3.0.1"
102 | lint:
103 | dependency: "direct dev"
104 | description:
105 | name: lint
106 | sha256: f4bd4dbaa39f4ae8836f2d1275f2f32bc68b3a8cce0a0735dd1f7a601f06682a
107 | url: "https://pub.dev"
108 | source: hosted
109 | version: "2.1.2"
110 | lists:
111 | dependency: transitive
112 | description:
113 | name: lists
114 | sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27"
115 | url: "https://pub.dev"
116 | source: hosted
117 | version: "1.0.1"
118 | matcher:
119 | dependency: transitive
120 | description:
121 | name: matcher
122 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
123 | url: "https://pub.dev"
124 | source: hosted
125 | version: "0.12.16+1"
126 | material_color_utilities:
127 | dependency: transitive
128 | description:
129 | name: material_color_utilities
130 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
131 | url: "https://pub.dev"
132 | source: hosted
133 | version: "0.11.1"
134 | meta:
135 | dependency: "direct main"
136 | description:
137 | name: meta
138 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
139 | url: "https://pub.dev"
140 | source: hosted
141 | version: "1.15.0"
142 | mgrs_dart:
143 | dependency: transitive
144 | description:
145 | name: mgrs_dart
146 | sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7
147 | url: "https://pub.dev"
148 | source: hosted
149 | version: "2.0.0"
150 | path:
151 | dependency: transitive
152 | description:
153 | name: path
154 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
155 | url: "https://pub.dev"
156 | source: hosted
157 | version: "1.9.0"
158 | proj4dart:
159 | dependency: "direct main"
160 | description:
161 | name: proj4dart
162 | sha256: ecece8694cb026917f9e90c0e0593043c65051e516aa9e6cd0f6f8c48485262e
163 | url: "https://pub.dev"
164 | source: hosted
165 | version: "2.0.0"
166 | quiver:
167 | dependency: transitive
168 | description:
169 | name: quiver
170 | sha256: "616b691d1c8f5c53b7b39ce3542f6a25308d7900bf689d0210e72a644a10387e"
171 | url: "https://pub.dev"
172 | source: hosted
173 | version: "3.0.1+1"
174 | sky_engine:
175 | dependency: transitive
176 | description: flutter
177 | source: sdk
178 | version: "0.0.0"
179 | source_span:
180 | dependency: transitive
181 | description:
182 | name: source_span
183 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
184 | url: "https://pub.dev"
185 | source: hosted
186 | version: "1.10.0"
187 | stack_trace:
188 | dependency: transitive
189 | description:
190 | name: stack_trace
191 | sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
192 | url: "https://pub.dev"
193 | source: hosted
194 | version: "1.12.0"
195 | stream_channel:
196 | dependency: transitive
197 | description:
198 | name: stream_channel
199 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
200 | url: "https://pub.dev"
201 | source: hosted
202 | version: "2.1.2"
203 | string_scanner:
204 | dependency: transitive
205 | description:
206 | name: string_scanner
207 | sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
208 | url: "https://pub.dev"
209 | source: hosted
210 | version: "1.3.0"
211 | term_glyph:
212 | dependency: transitive
213 | description:
214 | name: term_glyph
215 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
216 | url: "https://pub.dev"
217 | source: hosted
218 | version: "1.2.1"
219 | test_api:
220 | dependency: transitive
221 | description:
222 | name: test_api
223 | sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
224 | url: "https://pub.dev"
225 | source: hosted
226 | version: "0.7.3"
227 | tuple:
228 | dependency: "direct main"
229 | description:
230 | name: tuple
231 | sha256: fe3ae4f0dca3f9aac0888e2e0d117b642ce283a82d7017b54136290c0a3b0dd3
232 | url: "https://pub.dev"
233 | source: hosted
234 | version: "2.0.0"
235 | unicode:
236 | dependency: transitive
237 | description:
238 | name: unicode
239 | sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1"
240 | url: "https://pub.dev"
241 | source: hosted
242 | version: "0.3.1"
243 | vector_math:
244 | dependency: "direct main"
245 | description:
246 | name: vector_math
247 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
248 | url: "https://pub.dev"
249 | source: hosted
250 | version: "2.1.4"
251 | vm_service:
252 | dependency: transitive
253 | description:
254 | name: vm_service
255 | sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
256 | url: "https://pub.dev"
257 | source: hosted
258 | version: "14.3.0"
259 | wkt_parser:
260 | dependency: transitive
261 | description:
262 | name: wkt_parser
263 | sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13"
264 | url: "https://pub.dev"
265 | source: hosted
266 | version: "2.0.0"
267 | sdks:
268 | dart: ">=3.4.0 <4.0.0"
269 | flutter: ">=3.18.0-18.0.pre.54"
270 |
--------------------------------------------------------------------------------
/flutter_floating_map_marker_titles_core/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_floating_map_marker_titles_core
2 | description: Flutter Floating Map Marker Titles Core library
3 | version: 1.1.1
4 | repository: https://github.com/androidseb/flutter_map_floating_marker_titles
5 |
6 | environment:
7 | sdk: '>=2.17.1 <4.0.0'
8 | # This flutter >= 2.8.0 requirement is necessary for the web implementation to work:
9 | # https://github.com/flutter/flutter/issues/46683
10 | flutter: '>=2.8.0'
11 |
12 | dependencies:
13 | flutter:
14 | sdk: flutter
15 | latlong2: ^0.9.0
16 | meta: ^1.7.0
17 | proj4dart: ^2.0.0
18 | tuple: ^2.0.0
19 | vector_math: ^2.1.0
20 |
21 | dev_dependencies:
22 | flutter_test:
23 | sdk: flutter
24 | lint: 2.1.2
25 |
--------------------------------------------------------------------------------
/flutter_map_floating_marker_titles/.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 |
--------------------------------------------------------------------------------
/flutter_map_floating_marker_titles/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.3.0] - 2025/03/04
2 |
3 | * Updated flutter_map dependency to flutter_map: ^8.0.0
4 |
5 | ## [1.2.0] - 2024/08/10
6 |
7 | * Updated flutter_map dependency to flutter_map: ^7.0.2
8 | * Updated flutter_floating_map_marker_titles_core dependency to flutter_floating_map_marker_titles_core: ^1.1.0
9 |
10 | ## [1.1.0] - 2023/10/09
11 |
12 | * Updated flutter_map dependency to flutter_map: ^6.0.0
13 | * Added the `FloatingMarkerTitlesLayer` widget to use in flutter_map as a layer
14 |
15 | ## [1.0.0] - 2023/06/22
16 |
17 | * Updated the semantic version prefix to "officially stable" 1.X.X, because this library has been successful in a production app (see https://mapmarker.app) used by thousands of daily users for several months
18 | * Updated flutter_map dependency to flutter_map: ^5.0.0
19 | * Updated latlong2 dependency to latlong2: ^0.9.0
20 |
21 | ## [0.4.1] - 2023/05/07
22 |
23 | * Updated flutter_map dependency to flutter_map: ^4.0.0
24 |
25 | ## [0.4.0] - 2022/11/11
26 |
27 | * Updated flutter_map dependency to flutter_map: ^3.0.0
28 |
29 | ## [0.3.0] - 2022/10/23
30 |
31 | * Improved the logic handling the appearance for higher z-index titles
32 |
33 | ## [0.2.0] - 2022/09/15
34 |
35 | * Added the ability to set floating marker titles with a stream with the `floatingTitlesStream` parameter
36 |
37 | ## [0.1.0] - 2022/09/02
38 |
39 | * Changed the versioning pattern to leave the last digit for minor non-feature-related changes (e.g. library upgrades)
40 | * Updated dependencies to use flutter_map: ^2.2.0
41 |
42 | ## [0.0.6] - 2022/06/11
43 |
44 | Updated dependencies to use flutter_map: ^1.0.0
45 |
46 | ## [0.0.5+5] - 2022/01/09
47 |
48 | Removed web-specific code working around [a bug](https://github.com/flutter/flutter/issues/46683) that has since then been fixed.
49 |
50 | ## [0.0.4+4] - 2021/11/29
51 |
52 | Migrated to null safety.
53 |
54 | ## [0.0.3+3] - 2021/06/01
55 |
56 | Updated dependencies to use flutter_map: ^0.12.0
57 |
58 | ## [0.0.2+2] - 2021/04/01
59 |
60 | Fixed some issues with floating titles data not being updated in some cases, due to a wrong widget state setup.
61 |
62 | ## [0.0.1+1] - 2021/01/30
63 |
64 | This is the initial release of the library.
65 |
66 | * Support for floating map marker titles on flutter_map
67 |
--------------------------------------------------------------------------------
/flutter_map_floating_marker_titles/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, androidseb
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/flutter_map_floating_marker_titles/README.md:
--------------------------------------------------------------------------------
1 | # Flutter Map Floating Map Marker Titles
2 |
3 | Floating Map Marker Titles for [flutter_map](https://github.com/fleaflet/flutter_map), using the core library of the [Flutter Floating Map Marker Titles](https://github.com/androidseb/flutter_map_floating_marker_titles) project.
4 |
5 | ## Code example
6 |
7 | ```dart
8 | // With the FlutterMapWithFMTO widget as a FlutterMap wrapper
9 | FlutterMapWithFMTO(
10 | floatingTitles: floatingTitles,
11 | fmtoOptions: fmtoOptions,
12 | // ... other than the 2 above option, this widget takes
13 | // exactly the same props as the FlutterMap widget.
14 | options: MapOptions(
15 | center: LatLng(0, 0),
16 | zoom: 13,
17 | ),
18 | children: [
19 | TileLayer(
20 | urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
21 | ),
22 | ],
23 | )
24 |
25 | // Or with the FloatingMarkerTitlesLayer widget as a FlutterMap layer
26 | FlutterMap(
27 | options: MapOptions(
28 | center: LatLng(0, 0),
29 | zoom: 13,
30 | ),
31 | children: [
32 | TileLayer(
33 | urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
34 | ),
35 | FloatingMarkerTitlesLayer(
36 | floatingTitles: floatingTitles,
37 | fmtoOptions: fmtoOptions,
38 | ),
39 | ],
40 | )
41 | ```
42 |
43 | See the [how-to](https://github.com/androidseb/flutter_map_floating_marker_titles#how-to-use-this-library-in-your-code) section of the main project for more details.
44 |
--------------------------------------------------------------------------------
/flutter_map_floating_marker_titles/lib/flutter_map_floating_marker_titles.dart:
--------------------------------------------------------------------------------
1 | library flutter_map_floating_marker_titles;
2 |
3 | import 'package:flutter/widgets.dart';
4 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
5 | import 'package:flutter_floating_map_marker_titles_core/controller/map_view_interface/abstract_map_view_interface.dart';
6 | import 'package:flutter_floating_map_marker_titles_core/model/floating_marker_title_info.dart';
7 | import 'package:flutter_floating_map_marker_titles_core/view/floating_marker_titles_overlay.dart';
8 | import 'package:flutter_floating_map_marker_titles_core/controller/map_view_interface/abstract_czr_map_view_interface.dart';
9 | import 'package:flutter_floating_map_marker_titles_core/view/abstract_map_view_wrapper.dart';
10 | import 'package:flutter/material.dart';
11 | import 'package:flutter_map/flutter_map.dart';
12 | import 'package:latlong2/latlong.dart';
13 | import 'dart:async';
14 |
15 | class FlutterMapWithFMTO extends AbstractMapViewWrapper<_FlutterMapMVI> {
16 | final MapOptions _mapOptions;
17 | final List _children;
18 |
19 | factory FlutterMapWithFMTO({
20 | required final FMTOOptions fmtoOptions,
21 | required final MapOptions options,
22 | final Key? key,
23 | final List? floatingTitles,
24 | final Stream>? floatingTitlesStream,
25 | final List children = const [],
26 | final MapController? mapController,
27 | }) {
28 | return FlutterMapWithFMTO._internal(
29 | _FlutterMapMVI(mapController ?? MapController(), fmtoOptions.mapProjectionsCacheSize),
30 | fmtoOptions,
31 | key,
32 | options,
33 | children,
34 | floatingTitles: floatingTitles,
35 | floatingTitlesStream: floatingTitlesStream,
36 | );
37 | }
38 |
39 | FlutterMapWithFMTO._internal(
40 | final _FlutterMapMVI mapViewInterface,
41 | final FMTOOptions fmtoOptions,
42 | final Key? key,
43 | this._mapOptions,
44 | this._children, {
45 | final List? floatingTitles,
46 | final Stream>? floatingTitlesStream,
47 | }) : super(
48 | mapViewInterface,
49 | fmtoOptions,
50 | key: key,
51 | floatingTitles: floatingTitles,
52 | floatingTitlesStream: floatingTitlesStream,
53 | );
54 |
55 | @override
56 | Widget buildMapView(final BuildContext context, final _FlutterMapMVI mapViewInterface) {
57 | return FlutterMap(
58 | options: _mapOptions,
59 | children: _children,
60 | mapController: mapViewInterface.mapController,
61 | );
62 | }
63 | }
64 |
65 | class FloatingMarkerTitlesLayer extends StatelessWidget {
66 | final FMTOOptions fmtoOptions;
67 | final List? floatingTitles;
68 | final Stream>? floatingTitlesStream;
69 |
70 | const FloatingMarkerTitlesLayer({
71 | required this.fmtoOptions,
72 | super.key,
73 | this.floatingTitles,
74 | this.floatingTitlesStream,
75 | });
76 |
77 | @override
78 | Widget build(BuildContext context) {
79 | final MapController mapController = MapController.of(context);
80 | final _FlutterMapMVI _mapViewInterface = _FlutterMapMVI(mapController, fmtoOptions.mapProjectionsCacheSize);
81 | return FlutterMapFloatingMarkerTitlesOverlay(
82 | _mapViewInterface,
83 | fmtoOptions,
84 | floatingTitles: floatingTitles,
85 | floatingTitlesStream: floatingTitlesStream,
86 | );
87 | }
88 | }
89 |
90 | class _FlutterMapMVI extends AbstractCZRMapViewInterface {
91 | MapController mapController;
92 |
93 | _FlutterMapMVI(
94 | this.mapController,
95 | final int projCacheSize,
96 | ) : super(projCacheSize);
97 |
98 | @override
99 | void updateFrom(final AbstractMapViewInterface oldMapInterface) {
100 | super.updateFrom(oldMapInterface);
101 | if (oldMapInterface is _FlutterMapMVI) {
102 | mapController = oldMapInterface.mapController;
103 | }
104 | }
105 |
106 | @override
107 | LatLng getMapViewCenter() {
108 | return mapController.camera.center;
109 | }
110 |
111 | @override
112 | double getMapViewZoom() {
113 | return mapController.camera.zoom;
114 | }
115 |
116 | @override
117 | double getMapViewRotationDegrees() {
118 | return mapController.camera.rotation;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/flutter_map_floating_marker_titles/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | charcode:
29 | dependency: transitive
30 | description:
31 | name: charcode
32 | sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.3.1"
36 | clock:
37 | dependency: transitive
38 | description:
39 | name: clock
40 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.1.1"
44 | collection:
45 | dependency: transitive
46 | description:
47 | name: collection
48 | sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.19.0"
52 | dart_earcut:
53 | dependency: transitive
54 | description:
55 | name: dart_earcut
56 | sha256: "41b493147e30a051efb2da1e3acb7f38fe0db60afba24ac1ea5684cee272721e"
57 | url: "https://pub.dev"
58 | source: hosted
59 | version: "1.1.0"
60 | fake_async:
61 | dependency: transitive
62 | description:
63 | name: fake_async
64 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
65 | url: "https://pub.dev"
66 | source: hosted
67 | version: "1.3.1"
68 | flutter:
69 | dependency: "direct main"
70 | description: flutter
71 | source: sdk
72 | version: "0.0.0"
73 | flutter_floating_map_marker_titles_core:
74 | dependency: "direct main"
75 | description:
76 | name: flutter_floating_map_marker_titles_core
77 | sha256: "4ec34fbb4c4ab99c43c1a3a29fd5e3954354e979005dfea2af1da61887d74054"
78 | url: "https://pub.dev"
79 | source: hosted
80 | version: "1.1.0"
81 | flutter_map:
82 | dependency: "direct main"
83 | description:
84 | name: flutter_map
85 | sha256: bbf145e8220531f2f727608c431871c7457f3b134e513543913afd00fdc1cd47
86 | url: "https://pub.dev"
87 | source: hosted
88 | version: "8.1.0"
89 | flutter_test:
90 | dependency: "direct dev"
91 | description: flutter
92 | source: sdk
93 | version: "0.0.0"
94 | http:
95 | dependency: transitive
96 | description:
97 | name: http
98 | sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
99 | url: "https://pub.dev"
100 | source: hosted
101 | version: "1.2.2"
102 | http_parser:
103 | dependency: transitive
104 | description:
105 | name: http_parser
106 | sha256: e362d639ba3bc07d5a71faebb98cde68c05bfbcfbbb444b60b6f60bb67719185
107 | url: "https://pub.dev"
108 | source: hosted
109 | version: "4.0.0"
110 | intl:
111 | dependency: transitive
112 | description:
113 | name: intl
114 | sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
115 | url: "https://pub.dev"
116 | source: hosted
117 | version: "0.17.0"
118 | latlong2:
119 | dependency: "direct main"
120 | description:
121 | name: latlong2
122 | sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe"
123 | url: "https://pub.dev"
124 | source: hosted
125 | version: "0.9.1"
126 | leak_tracker:
127 | dependency: transitive
128 | description:
129 | name: leak_tracker
130 | sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
131 | url: "https://pub.dev"
132 | source: hosted
133 | version: "10.0.7"
134 | leak_tracker_flutter_testing:
135 | dependency: transitive
136 | description:
137 | name: leak_tracker_flutter_testing
138 | sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
139 | url: "https://pub.dev"
140 | source: hosted
141 | version: "3.0.8"
142 | leak_tracker_testing:
143 | dependency: transitive
144 | description:
145 | name: leak_tracker_testing
146 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
147 | url: "https://pub.dev"
148 | source: hosted
149 | version: "3.0.1"
150 | lint:
151 | dependency: "direct dev"
152 | description:
153 | name: lint
154 | sha256: f4bd4dbaa39f4ae8836f2d1275f2f32bc68b3a8cce0a0735dd1f7a601f06682a
155 | url: "https://pub.dev"
156 | source: hosted
157 | version: "2.1.2"
158 | lists:
159 | dependency: transitive
160 | description:
161 | name: lists
162 | sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27"
163 | url: "https://pub.dev"
164 | source: hosted
165 | version: "1.0.1"
166 | logger:
167 | dependency: transitive
168 | description:
169 | name: logger
170 | sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac"
171 | url: "https://pub.dev"
172 | source: hosted
173 | version: "2.0.2+1"
174 | matcher:
175 | dependency: transitive
176 | description:
177 | name: matcher
178 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
179 | url: "https://pub.dev"
180 | source: hosted
181 | version: "0.12.16+1"
182 | material_color_utilities:
183 | dependency: transitive
184 | description:
185 | name: material_color_utilities
186 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
187 | url: "https://pub.dev"
188 | source: hosted
189 | version: "0.11.1"
190 | meta:
191 | dependency: transitive
192 | description:
193 | name: meta
194 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
195 | url: "https://pub.dev"
196 | source: hosted
197 | version: "1.15.0"
198 | mgrs_dart:
199 | dependency: transitive
200 | description:
201 | name: mgrs_dart
202 | sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7
203 | url: "https://pub.dev"
204 | source: hosted
205 | version: "2.0.0"
206 | path:
207 | dependency: transitive
208 | description:
209 | name: path
210 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
211 | url: "https://pub.dev"
212 | source: hosted
213 | version: "1.9.0"
214 | polylabel:
215 | dependency: transitive
216 | description:
217 | name: polylabel
218 | sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b"
219 | url: "https://pub.dev"
220 | source: hosted
221 | version: "1.0.1"
222 | proj4dart:
223 | dependency: transitive
224 | description:
225 | name: proj4dart
226 | sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e
227 | url: "https://pub.dev"
228 | source: hosted
229 | version: "2.1.0"
230 | quiver:
231 | dependency: transitive
232 | description:
233 | name: quiver
234 | sha256: "616b691d1c8f5c53b7b39ce3542f6a25308d7900bf689d0210e72a644a10387e"
235 | url: "https://pub.dev"
236 | source: hosted
237 | version: "3.0.1+1"
238 | sky_engine:
239 | dependency: transitive
240 | description: flutter
241 | source: sdk
242 | version: "0.0.0"
243 | source_span:
244 | dependency: transitive
245 | description:
246 | name: source_span
247 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
248 | url: "https://pub.dev"
249 | source: hosted
250 | version: "1.10.0"
251 | stack_trace:
252 | dependency: transitive
253 | description:
254 | name: stack_trace
255 | sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
256 | url: "https://pub.dev"
257 | source: hosted
258 | version: "1.12.0"
259 | stream_channel:
260 | dependency: transitive
261 | description:
262 | name: stream_channel
263 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
264 | url: "https://pub.dev"
265 | source: hosted
266 | version: "2.1.2"
267 | string_scanner:
268 | dependency: transitive
269 | description:
270 | name: string_scanner
271 | sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
272 | url: "https://pub.dev"
273 | source: hosted
274 | version: "1.3.0"
275 | term_glyph:
276 | dependency: transitive
277 | description:
278 | name: term_glyph
279 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
280 | url: "https://pub.dev"
281 | source: hosted
282 | version: "1.2.1"
283 | test_api:
284 | dependency: transitive
285 | description:
286 | name: test_api
287 | sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
288 | url: "https://pub.dev"
289 | source: hosted
290 | version: "0.7.3"
291 | tuple:
292 | dependency: transitive
293 | description:
294 | name: tuple
295 | sha256: fe3ae4f0dca3f9aac0888e2e0d117b642ce283a82d7017b54136290c0a3b0dd3
296 | url: "https://pub.dev"
297 | source: hosted
298 | version: "2.0.0"
299 | typed_data:
300 | dependency: transitive
301 | description:
302 | name: typed_data
303 | sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee"
304 | url: "https://pub.dev"
305 | source: hosted
306 | version: "1.3.0"
307 | unicode:
308 | dependency: transitive
309 | description:
310 | name: unicode
311 | sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1"
312 | url: "https://pub.dev"
313 | source: hosted
314 | version: "0.3.1"
315 | vector_math:
316 | dependency: transitive
317 | description:
318 | name: vector_math
319 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
320 | url: "https://pub.dev"
321 | source: hosted
322 | version: "2.1.4"
323 | vm_service:
324 | dependency: transitive
325 | description:
326 | name: vm_service
327 | sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
328 | url: "https://pub.dev"
329 | source: hosted
330 | version: "14.3.0"
331 | web:
332 | dependency: transitive
333 | description:
334 | name: web
335 | sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
336 | url: "https://pub.dev"
337 | source: hosted
338 | version: "1.0.0"
339 | wkt_parser:
340 | dependency: transitive
341 | description:
342 | name: wkt_parser
343 | sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13"
344 | url: "https://pub.dev"
345 | source: hosted
346 | version: "2.0.0"
347 | sdks:
348 | dart: ">=3.6.0 <4.0.0"
349 | flutter: ">=3.27.0"
350 |
--------------------------------------------------------------------------------
/flutter_map_floating_marker_titles/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_map_floating_marker_titles
2 | description: Floating Map Marker Titles for flutter_map
3 | version: 1.3.0
4 | repository: https://github.com/androidseb/flutter_map_floating_marker_titles
5 |
6 | environment:
7 | sdk: '>=2.17.1 <4.0.0'
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 |
13 | latlong2: ^0.9.0
14 |
15 | flutter_floating_map_marker_titles_core: ^1.1.0
16 | # Uncomment and use this a dependency when working locally
17 | #flutter_floating_map_marker_titles_core:
18 | # path: ../flutter_floating_map_marker_titles_core
19 | flutter_map: ^8.0.0
20 |
21 | dev_dependencies:
22 | flutter_test:
23 | sdk: flutter
24 | lint: 2.1.2
25 |
--------------------------------------------------------------------------------
/google_maps_flutter_floating_marker_titles/.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 |
--------------------------------------------------------------------------------
/google_maps_flutter_floating_marker_titles/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.1.0] - 2024/08/10
2 |
3 | * Updated flutter_floating_map_marker_titles_core dependency to flutter_floating_map_marker_titles_core: ^1.1.0
4 |
5 | ## [1.0.0] - 2023/06/22
6 |
7 | * Updated the semantic version prefix to "officially stable" 1.X.X, because this library has been successful in a production app (see https://mapmarker.app) used by thousands of daily users for several months
8 | * Updated latlong2 dependency to latlong2: ^0.9.0
9 |
10 | ## [0.3.0] - 2022/10/23
11 |
12 | * Improved the logic handling the appearance for higher z-index titles
13 |
14 | ## [0.2.0] - 2022/09/15
15 |
16 | * Added the ability to set floating marker titles with a stream with the `floatingTitlesStream` parameter
17 | * Updated dependencies to use google_maps_flutter: ^2.2.0
18 |
19 | ## [0.1.0] - 2022/09/02
20 |
21 | * Changed the versioning pattern to leave the last digit for minor non-feature-related changes (e.g. library upgrades)
22 |
23 | ## [0.0.6] - 2022/06/11
24 |
25 | Fixed titles being placed incorrectly when the map is rotated.
26 |
27 | ## [0.0.5+5] - 2022/01/09
28 |
29 | Removed web-specific code working around [a bug](https://github.com/flutter/flutter/issues/46683) that has since then been fixed.
30 |
31 | ## [0.0.4+4] - 2021/11/29
32 |
33 | Migrated to null safety.
34 |
35 | ## [0.0.3+3] - 2021/06/01
36 |
37 | Updated dependencies to use google_maps_flutter: ^2.0.4
38 |
39 | ## [0.0.2+2] - 2021/04/01
40 |
41 | Fixed some issues with floating titles data not being updated in some cases, due to a wrong widget state setup.
42 |
43 | ## [0.0.1+1] - 2021/01/30
44 |
45 | This is the initial release of the library.
46 |
47 | * Support for floating map marker titles on google_maps_flutter
48 |
--------------------------------------------------------------------------------
/google_maps_flutter_floating_marker_titles/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, androidseb
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/google_maps_flutter_floating_marker_titles/README.md:
--------------------------------------------------------------------------------
1 | # Flutter Map Floating Map Marker Titles
2 |
3 | Floating Map Marker Titles for [google_maps_flutter](https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter), using the core library of the [Flutter Floating Map Marker Titles](https://github.com/androidseb/flutter_map_floating_marker_titles) project.
4 |
5 | ## Code example
6 |
7 | ```dart
8 | GoogleMapWithFMTO(
9 | floatingTitles,
10 | fmtoOptions: fmtoOptions,
11 | // ... other than the 2 above option, this widget takes
12 | // exactly the same props as the GoogleMap widget.
13 | initialCameraPosition: CameraPosition(
14 | target: LatLng(0, 0),
15 | zoom: 13,
16 | ),
17 | )
18 | ```
19 |
20 | See the [how-to](https://github.com/androidseb/flutter_map_floating_marker_titles#how-to-use-this-library-in-your-code) section of the main project for more details.
21 |
--------------------------------------------------------------------------------
/google_maps_flutter_floating_marker_titles/lib/google_maps_flutter_floating_marker_titles.dart:
--------------------------------------------------------------------------------
1 | library google_maps_flutter_floating_marker_titles;
2 |
3 | import 'package:flutter/foundation.dart';
4 | import 'package:flutter/gestures.dart';
5 | import 'package:flutter/widgets.dart';
6 | import 'package:flutter_floating_map_marker_titles_core/controller/fmto_controller.dart';
7 | import 'package:flutter_floating_map_marker_titles_core/controller/map_view_interface/abstract_czr_map_view_interface.dart';
8 | import 'package:flutter_floating_map_marker_titles_core/controller/map_view_interface/abstract_map_view_interface.dart';
9 | import 'package:flutter_floating_map_marker_titles_core/model/floating_marker_title_info.dart';
10 | import 'package:flutter_floating_map_marker_titles_core/view/abstract_map_view_wrapper.dart';
11 | import 'package:flutter/material.dart';
12 | import 'package:google_maps_flutter/google_maps_flutter.dart';
13 | import 'package:latlong2/latlong.dart' as latlong;
14 |
15 | class GoogleMapWithFMTO extends AbstractMapViewWrapper<_GoogleMapMVI> {
16 | final CameraPosition _initialCameraPosition;
17 | final MapCreatedCallback? _onMapCreated;
18 | final Set>? _gestureRecognizers;
19 | final bool _compassEnabled;
20 | final bool _mapToolbarEnabled;
21 | final CameraTargetBounds _cameraTargetBounds;
22 | final MapType _mapType;
23 | final MinMaxZoomPreference _minMaxZoomPreference;
24 | final bool _rotateGesturesEnabled;
25 | final bool _scrollGesturesEnabled;
26 | final bool _zoomControlsEnabled;
27 | final bool _zoomGesturesEnabled;
28 | final bool _liteModeEnabled;
29 | final bool _tiltGesturesEnabled;
30 | final EdgeInsets _padding;
31 | final Set? _markers;
32 | final Set? _polygons;
33 | final Set? _polylines;
34 | final Set? _circles;
35 | final VoidCallback? _onCameraMoveStarted;
36 | final CameraPositionCallback? _onCameraMove;
37 | final VoidCallback? _onCameraIdle;
38 | final ArgumentCallback? _onTap;
39 | final ArgumentCallback? _onLongPress;
40 | final bool? _myLocationEnabled;
41 | final bool? _myLocationButtonEnabled;
42 | final bool? _indoorViewEnabled;
43 | final bool? _trafficEnabled;
44 | final bool? _buildingsEnabled;
45 |
46 | factory GoogleMapWithFMTO({
47 | required final FMTOOptions fmtoOptions,
48 | required final CameraPosition initialCameraPosition,
49 | final Key? key,
50 | final List? floatingTitles,
51 | final Stream>? floatingTitlesStream,
52 | final MapCreatedCallback? onMapCreated,
53 | final Set>? gestureRecognizers,
54 | final bool compassEnabled = true,
55 | final bool mapToolbarEnabled = true,
56 | final CameraTargetBounds cameraTargetBounds = CameraTargetBounds.unbounded,
57 | final MapType mapType = MapType.normal,
58 | final MinMaxZoomPreference minMaxZoomPreference = MinMaxZoomPreference.unbounded,
59 | final bool rotateGesturesEnabled = true,
60 | final bool scrollGesturesEnabled = true,
61 | final bool zoomControlsEnabled = true,
62 | final bool zoomGesturesEnabled = true,
63 | final bool liteModeEnabled = false,
64 | final bool tiltGesturesEnabled = true,
65 | final EdgeInsets padding = const EdgeInsets.all(0),
66 | final Set? markers,
67 | final Set? polygons,
68 | final Set? polylines,
69 | final Set? circles,
70 | final VoidCallback? onCameraMoveStarted,
71 | final CameraPositionCallback? onCameraMove,
72 | final VoidCallback? onCameraIdle,
73 | final ArgumentCallback? onTap,
74 | final ArgumentCallback? onLongPress,
75 | final bool? myLocationEnabled,
76 | final bool? myLocationButtonEnabled,
77 | final bool? indoorViewEnabled,
78 | final bool? trafficEnabled,
79 | final bool? buildingsEnabled,
80 | }) {
81 | return GoogleMapWithFMTO._internal(
82 | _GoogleMapMVI(fmtoOptions.mapProjectionsCacheSize),
83 | fmtoOptions,
84 | key,
85 | initialCameraPosition,
86 | onMapCreated,
87 | gestureRecognizers,
88 | compassEnabled,
89 | mapToolbarEnabled,
90 | cameraTargetBounds,
91 | mapType,
92 | minMaxZoomPreference,
93 | rotateGesturesEnabled,
94 | scrollGesturesEnabled,
95 | zoomControlsEnabled,
96 | zoomGesturesEnabled,
97 | liteModeEnabled,
98 | tiltGesturesEnabled,
99 | padding,
100 | markers,
101 | polygons,
102 | polylines,
103 | circles,
104 | onCameraMoveStarted,
105 | onCameraMove,
106 | onCameraIdle,
107 | onTap,
108 | onLongPress,
109 | myLocationEnabled,
110 | myLocationButtonEnabled,
111 | indoorViewEnabled,
112 | trafficEnabled,
113 | buildingsEnabled,
114 | floatingTitles: floatingTitles,
115 | floatingTitlesStream: floatingTitlesStream,
116 | );
117 | }
118 |
119 | GoogleMapWithFMTO._internal(
120 | final _GoogleMapMVI mapViewInterface,
121 | final FMTOOptions fmtoOptions,
122 | final Key? key,
123 | this._initialCameraPosition,
124 | this._onMapCreated,
125 | this._gestureRecognizers,
126 | this._compassEnabled,
127 | this._mapToolbarEnabled,
128 | this._cameraTargetBounds,
129 | this._mapType,
130 | this._minMaxZoomPreference,
131 | this._rotateGesturesEnabled,
132 | this._scrollGesturesEnabled,
133 | this._zoomControlsEnabled,
134 | this._zoomGesturesEnabled,
135 | this._liteModeEnabled,
136 | this._tiltGesturesEnabled,
137 | this._padding,
138 | this._markers,
139 | this._polygons,
140 | this._polylines,
141 | this._circles,
142 | this._onCameraMoveStarted,
143 | this._onCameraMove,
144 | this._onCameraIdle,
145 | this._onTap,
146 | this._onLongPress,
147 | this._myLocationEnabled,
148 | this._myLocationButtonEnabled,
149 | this._indoorViewEnabled,
150 | this._trafficEnabled,
151 | this._buildingsEnabled, {
152 | final List? floatingTitles,
153 | final Stream>? floatingTitlesStream,
154 | }) : super(
155 | mapViewInterface,
156 | fmtoOptions,
157 | key: key,
158 | floatingTitles: floatingTitles,
159 | floatingTitlesStream: floatingTitlesStream,
160 | ) {
161 | mapViewInterface.cameraPosition = this._initialCameraPosition;
162 | }
163 |
164 | @override
165 | Widget buildMapView(final BuildContext context, final _GoogleMapMVI mapViewInterface) {
166 | return GoogleMap(
167 | initialCameraPosition: _initialCameraPosition,
168 | onMapCreated: _onMapCreated,
169 | gestureRecognizers: _gestureRecognizers ?? const >{},
170 | compassEnabled: _compassEnabled,
171 | mapToolbarEnabled: _mapToolbarEnabled,
172 | cameraTargetBounds: _cameraTargetBounds,
173 | mapType: _mapType,
174 | minMaxZoomPreference: _minMaxZoomPreference,
175 | rotateGesturesEnabled: _rotateGesturesEnabled,
176 | scrollGesturesEnabled: _scrollGesturesEnabled,
177 | zoomControlsEnabled: _zoomControlsEnabled,
178 | zoomGesturesEnabled: _zoomGesturesEnabled,
179 | liteModeEnabled: _liteModeEnabled,
180 | tiltGesturesEnabled: _tiltGesturesEnabled,
181 | myLocationEnabled: _myLocationEnabled ?? false,
182 | myLocationButtonEnabled: _myLocationButtonEnabled ?? true,
183 | padding: _padding,
184 | indoorViewEnabled: _indoorViewEnabled ?? false,
185 | trafficEnabled: _trafficEnabled ?? false,
186 | buildingsEnabled: _buildingsEnabled ?? true,
187 | markers: _markers ?? const {},
188 | polygons: _polygons ?? const {},
189 | polylines: _polylines ?? const {},
190 | circles: _circles ?? const {},
191 | onCameraMoveStarted: _onCameraMoveStarted,
192 | onCameraMove: (final CameraPosition newPosition) {
193 | _onCameraMove?.call(newPosition);
194 | mapViewInterface.cameraPosition = newPosition;
195 | },
196 | onCameraIdle: _onCameraIdle,
197 | onTap: _onTap,
198 | onLongPress: _onLongPress,
199 | );
200 | }
201 | }
202 |
203 | class _GoogleMapMVI extends AbstractCZRMapViewInterface {
204 | CameraPosition? cameraPosition;
205 |
206 | _GoogleMapMVI(final int projCacheSize) : super(projCacheSize);
207 |
208 | @override
209 | void updateFrom(final AbstractMapViewInterface oldMapInterface) {
210 | super.updateFrom(oldMapInterface);
211 | if (oldMapInterface is _GoogleMapMVI) {
212 | cameraPosition = oldMapInterface.cameraPosition;
213 | }
214 | }
215 |
216 | @override
217 | latlong.LatLng getMapViewCenter() {
218 | final double? latitude = cameraPosition?.target.latitude;
219 | final double? longitude = cameraPosition?.target.longitude;
220 | if (latitude == null || longitude == null || latitude.isNaN || longitude.isNaN) {
221 | return latlong.LatLng(0, 0);
222 | }
223 | return latlong.LatLng(
224 | latitude,
225 | longitude,
226 | );
227 | }
228 |
229 | @override
230 | double getMapViewZoom() {
231 | final double? zoom = cameraPosition?.zoom;
232 | if (zoom == null || zoom.isNaN) {
233 | return 1;
234 | }
235 | return zoom;
236 | }
237 |
238 | @override
239 | double getMapViewRotationDegrees() {
240 | final double? bearing = cameraPosition?.bearing;
241 | if (bearing == null || bearing.isNaN) {
242 | return 1;
243 | }
244 | return -bearing;
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/google_maps_flutter_floating_marker_titles/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
9 | url: "https://pub.dev"
10 | source: hosted
11 | version: "2.11.0"
12 | boolean_selector:
13 | dependency: transitive
14 | description:
15 | name: boolean_selector
16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
17 | url: "https://pub.dev"
18 | source: hosted
19 | version: "2.1.1"
20 | characters:
21 | dependency: transitive
22 | description:
23 | name: characters
24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
25 | url: "https://pub.dev"
26 | source: hosted
27 | version: "1.3.0"
28 | clock:
29 | dependency: transitive
30 | description:
31 | name: clock
32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
33 | url: "https://pub.dev"
34 | source: hosted
35 | version: "1.1.1"
36 | collection:
37 | dependency: transitive
38 | description:
39 | name: collection
40 | sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
41 | url: "https://pub.dev"
42 | source: hosted
43 | version: "1.19.0"
44 | fake_async:
45 | dependency: transitive
46 | description:
47 | name: fake_async
48 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
49 | url: "https://pub.dev"
50 | source: hosted
51 | version: "1.3.1"
52 | flutter:
53 | dependency: "direct main"
54 | description: flutter
55 | source: sdk
56 | version: "0.0.0"
57 | flutter_floating_map_marker_titles_core:
58 | dependency: "direct main"
59 | description:
60 | name: flutter_floating_map_marker_titles_core
61 | sha256: "4ec34fbb4c4ab99c43c1a3a29fd5e3954354e979005dfea2af1da61887d74054"
62 | url: "https://pub.dev"
63 | source: hosted
64 | version: "1.1.0"
65 | flutter_plugin_android_lifecycle:
66 | dependency: transitive
67 | description:
68 | name: flutter_plugin_android_lifecycle
69 | sha256: aa36b33c721ac6e889adad07e3c87e6a07b33c28d1f2bc22f2561762cd7d2162
70 | url: "https://pub.dev"
71 | source: hosted
72 | version: "2.0.2"
73 | flutter_test:
74 | dependency: "direct dev"
75 | description: flutter
76 | source: sdk
77 | version: "0.0.0"
78 | google_maps_flutter:
79 | dependency: "direct main"
80 | description:
81 | name: google_maps_flutter
82 | sha256: "07f81e2d26a4dd2664e3beed547c75eb24b780c5c8519cd42bc0137308a1e7f6"
83 | url: "https://pub.dev"
84 | source: hosted
85 | version: "2.2.0"
86 | google_maps_flutter_android:
87 | dependency: transitive
88 | description:
89 | name: google_maps_flutter_android
90 | sha256: "7e0234029f1e2531203ea735e0bf69a0a25a6c6d62a19b7cac756f87062c8f5a"
91 | url: "https://pub.dev"
92 | source: hosted
93 | version: "2.3.0"
94 | google_maps_flutter_ios:
95 | dependency: transitive
96 | description:
97 | name: google_maps_flutter_ios
98 | sha256: "71213e497600e0c67cf7a096f643e58a72ed36334456c32c7ae0a6b4698018df"
99 | url: "https://pub.dev"
100 | source: hosted
101 | version: "2.1.11"
102 | google_maps_flutter_platform_interface:
103 | dependency: transitive
104 | description:
105 | name: google_maps_flutter_platform_interface
106 | sha256: "0a91acaa7ab6a438f428efe49f145a2b48f18ff039301ee2232696e18bf78784"
107 | url: "https://pub.dev"
108 | source: hosted
109 | version: "2.2.2"
110 | intl:
111 | dependency: transitive
112 | description:
113 | name: intl
114 | sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
115 | url: "https://pub.dev"
116 | source: hosted
117 | version: "0.17.0"
118 | latlong2:
119 | dependency: "direct main"
120 | description:
121 | name: latlong2
122 | sha256: "18712164760cee655bc790122b0fd8f3d5b3c36da2cb7bf94b68a197fbb0811b"
123 | url: "https://pub.dev"
124 | source: hosted
125 | version: "0.9.0"
126 | leak_tracker:
127 | dependency: transitive
128 | description:
129 | name: leak_tracker
130 | sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
131 | url: "https://pub.dev"
132 | source: hosted
133 | version: "10.0.7"
134 | leak_tracker_flutter_testing:
135 | dependency: transitive
136 | description:
137 | name: leak_tracker_flutter_testing
138 | sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
139 | url: "https://pub.dev"
140 | source: hosted
141 | version: "3.0.8"
142 | leak_tracker_testing:
143 | dependency: transitive
144 | description:
145 | name: leak_tracker_testing
146 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
147 | url: "https://pub.dev"
148 | source: hosted
149 | version: "3.0.1"
150 | lint:
151 | dependency: "direct dev"
152 | description:
153 | name: lint
154 | sha256: f4bd4dbaa39f4ae8836f2d1275f2f32bc68b3a8cce0a0735dd1f7a601f06682a
155 | url: "https://pub.dev"
156 | source: hosted
157 | version: "2.1.2"
158 | lists:
159 | dependency: transitive
160 | description:
161 | name: lists
162 | sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27"
163 | url: "https://pub.dev"
164 | source: hosted
165 | version: "1.0.1"
166 | matcher:
167 | dependency: transitive
168 | description:
169 | name: matcher
170 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
171 | url: "https://pub.dev"
172 | source: hosted
173 | version: "0.12.16+1"
174 | material_color_utilities:
175 | dependency: transitive
176 | description:
177 | name: material_color_utilities
178 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
179 | url: "https://pub.dev"
180 | source: hosted
181 | version: "0.11.1"
182 | meta:
183 | dependency: transitive
184 | description:
185 | name: meta
186 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
187 | url: "https://pub.dev"
188 | source: hosted
189 | version: "1.15.0"
190 | mgrs_dart:
191 | dependency: transitive
192 | description:
193 | name: mgrs_dart
194 | sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7
195 | url: "https://pub.dev"
196 | source: hosted
197 | version: "2.0.0"
198 | path:
199 | dependency: transitive
200 | description:
201 | name: path
202 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
203 | url: "https://pub.dev"
204 | source: hosted
205 | version: "1.9.0"
206 | plugin_platform_interface:
207 | dependency: transitive
208 | description:
209 | name: plugin_platform_interface
210 | sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a
211 | url: "https://pub.dev"
212 | source: hosted
213 | version: "2.1.3"
214 | proj4dart:
215 | dependency: transitive
216 | description:
217 | name: proj4dart
218 | sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e
219 | url: "https://pub.dev"
220 | source: hosted
221 | version: "2.1.0"
222 | sky_engine:
223 | dependency: transitive
224 | description: flutter
225 | source: sdk
226 | version: "0.0.0"
227 | source_span:
228 | dependency: transitive
229 | description:
230 | name: source_span
231 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
232 | url: "https://pub.dev"
233 | source: hosted
234 | version: "1.10.0"
235 | stack_trace:
236 | dependency: transitive
237 | description:
238 | name: stack_trace
239 | sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
240 | url: "https://pub.dev"
241 | source: hosted
242 | version: "1.12.0"
243 | stream_channel:
244 | dependency: transitive
245 | description:
246 | name: stream_channel
247 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
248 | url: "https://pub.dev"
249 | source: hosted
250 | version: "2.1.2"
251 | stream_transform:
252 | dependency: transitive
253 | description:
254 | name: stream_transform
255 | sha256: ed464977cb26a1f41537e177e190c67223dbd9f4f683489b6ab2e5d211ec564e
256 | url: "https://pub.dev"
257 | source: hosted
258 | version: "2.0.0"
259 | string_scanner:
260 | dependency: transitive
261 | description:
262 | name: string_scanner
263 | sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
264 | url: "https://pub.dev"
265 | source: hosted
266 | version: "1.3.0"
267 | term_glyph:
268 | dependency: transitive
269 | description:
270 | name: term_glyph
271 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
272 | url: "https://pub.dev"
273 | source: hosted
274 | version: "1.2.1"
275 | test_api:
276 | dependency: transitive
277 | description:
278 | name: test_api
279 | sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
280 | url: "https://pub.dev"
281 | source: hosted
282 | version: "0.7.3"
283 | tuple:
284 | dependency: transitive
285 | description:
286 | name: tuple
287 | sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
288 | url: "https://pub.dev"
289 | source: hosted
290 | version: "2.0.2"
291 | unicode:
292 | dependency: transitive
293 | description:
294 | name: unicode
295 | sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1"
296 | url: "https://pub.dev"
297 | source: hosted
298 | version: "0.3.1"
299 | vector_math:
300 | dependency: transitive
301 | description:
302 | name: vector_math
303 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
304 | url: "https://pub.dev"
305 | source: hosted
306 | version: "2.1.4"
307 | vm_service:
308 | dependency: transitive
309 | description:
310 | name: vm_service
311 | sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
312 | url: "https://pub.dev"
313 | source: hosted
314 | version: "14.3.0"
315 | wkt_parser:
316 | dependency: transitive
317 | description:
318 | name: wkt_parser
319 | sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13"
320 | url: "https://pub.dev"
321 | source: hosted
322 | version: "2.0.0"
323 | sdks:
324 | dart: ">=3.4.0 <4.0.0"
325 | flutter: ">=3.18.0-18.0.pre.54"
326 |
--------------------------------------------------------------------------------
/google_maps_flutter_floating_marker_titles/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: google_maps_flutter_floating_marker_titles
2 | description: Floating Map Marker Titles for google_maps_flutter
3 | version: 1.1.0
4 | repository: https://github.com/androidseb/flutter_map_floating_marker_titles
5 |
6 | environment:
7 | sdk: '>=2.17.1 <4.0.0'
8 |
9 | dependencies:
10 | flutter:
11 | sdk: flutter
12 |
13 | latlong2: ^0.9.0
14 |
15 | flutter_floating_map_marker_titles_core: ^1.1.0
16 | # Uncomment and use this a dependency when working locally
17 | #flutter_floating_map_marker_titles_core:
18 | # path: ../flutter_floating_map_marker_titles_core
19 | google_maps_flutter: ^2.2.0
20 |
21 | dev_dependencies:
22 | flutter_test:
23 | sdk: flutter
24 | lint: 2.1.2
25 |
--------------------------------------------------------------------------------
/publish_checklist.md:
--------------------------------------------------------------------------------
1 | # Publish checklist
2 |
3 | This is just a cheat sheet for me when I publish a new library version for the following library folders:
4 | * `flutter_floating_map_marker_titles_core`
5 | * `flutter_map_floating_marker_titles`
6 | * `google_maps_flutter_floating_marker_titles`
7 |
8 | These steps are based on the [official documentation](https://flutter.dev/docs/development/packages-and-plugins/developing-packages).
9 |
10 | **Publishing steps:**
11 |
12 | * Branch off main with a temporary branch (e.g. "version/2025.03.04")
13 | * Update the version in `pubspec.yaml`
14 | * Update the changelog file `CHANGELOG.md` documenting the changes of that new version
15 | * Test the publishing with this command: `flutter pub publish --dry-run`
16 | * Actually publish with this command: `flutter pub publish`
17 | * Tag the version with git:
18 | * core library: `git tag -a "core_v1.1.0" -m "core_v1.1.0"`
19 | * flutter_map plugin: `git tag -a "fm_v1.2.0" -m "fm_v1.2.0"`
20 | * google_maps_flutter plugin: `git tag -a "gm_v1.1.0" -m "gm_v1.1.0"`
21 | * Push the tags with: `git push origin --tags`
22 | * Merge the temporary branch back into main
23 | * Delete the temporary branch
24 |
--------------------------------------------------------------------------------
/visual_demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/androidseb/flutter_map_floating_marker_titles/9834a35c0f0292e1c24dc91acb340e80f71bc388/visual_demo.gif
--------------------------------------------------------------------------------