diff --git a/example/.metadata b/example/.metadata
index b8041ab28..31ae8bd5c 100644
--- a/example/.metadata
+++ b/example/.metadata
@@ -4,8 +4,8 @@
# This file should be version controlled and should not be manually edited.
version:
- revision: "53c27e519d33b4e13b01a8710b38a3591d6ca6f1"
- channel: "beta"
+ revision: "463e7516406b4ba7814703616da0e475523db54c"
+ channel: "master"
project_type: app
@@ -13,11 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
- create_revision: 53c27e519d33b4e13b01a8710b38a3591d6ca6f1
- base_revision: 53c27e519d33b4e13b01a8710b38a3591d6ca6f1
- - platform: windows
- create_revision: 53c27e519d33b4e13b01a8710b38a3591d6ca6f1
- base_revision: 53c27e519d33b4e13b01a8710b38a3591d6ca6f1
+ create_revision: 463e7516406b4ba7814703616da0e475523db54c
+ base_revision: 463e7516406b4ba7814703616da0e475523db54c
+ - platform: ios
+ create_revision: 463e7516406b4ba7814703616da0e475523db54c
+ base_revision: 463e7516406b4ba7814703616da0e475523db54c
# User provided section
diff --git a/example/ios/.gitignore b/example/ios/.gitignore
index e96ef602b..7a7f9873a 100644
--- a/example/ios/.gitignore
+++ b/example/ios/.gitignore
@@ -1,3 +1,4 @@
+**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
@@ -18,6 +19,7 @@ Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
+Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist
index 9367d483e..7c5696400 100644
--- a/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 8.0
+ 12.0
diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig
index ec97fc6f3..592ceee85 100644
--- a/example/ios/Flutter/Debug.xcconfig
+++ b/example/ios/Flutter/Debug.xcconfig
@@ -1,2 +1 @@
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig
index c4855bfe2..592ceee85 100644
--- a/example/ios/Flutter/Release.xcconfig
+++ b/example/ios/Flutter/Release.xcconfig
@@ -1,2 +1 @@
-#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
diff --git a/example/ios/Podfile b/example/ios/Podfile
deleted file mode 100644
index 88359b225..000000000
--- a/example/ios/Podfile
+++ /dev/null
@@ -1,41 +0,0 @@
-# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
-
-# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
-ENV['COCOAPODS_DISABLE_STATS'] = 'true'
-
-project 'Runner', {
- 'Debug' => :debug,
- 'Profile' => :release,
- 'Release' => :release,
-}
-
-def flutter_root
- generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
- unless File.exist?(generated_xcode_build_settings_path)
- raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
- end
-
- File.foreach(generated_xcode_build_settings_path) do |line|
- matches = line.match(/FLUTTER_ROOT\=(.*)/)
- return matches[1].strip if matches
- end
- raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
-end
-
-require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
-
-flutter_ios_podfile_setup
-
-target 'Runner' do
- use_frameworks!
- use_modular_headers!
-
- flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
-end
-
-post_install do |installer|
- installer.pods_project.targets.each do |target|
- flutter_additional_ios_build_settings(target)
- end
-end
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index ab9fc9ecf..ee8e72be9 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -3,12 +3,12 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
- 127B2300FA5CE87549434CC2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A72EECE5117AE803156E244 /* Pods_Runner.framework */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
@@ -16,6 +16,16 @@
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
+/* Begin PBXContainerItemProxy section */
+ 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 97C146E61CF9000F007C117D /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 97C146ED1CF9000F007C117D;
+ remoteInfo = Runner;
+ };
+/* End PBXContainerItemProxy section */
+
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
@@ -32,9 +42,9 @@
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
- 3A72EECE5117AE803156E244 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
+ 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
- 4928082F7E2BC0BADA4A6955 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
@@ -45,8 +55,6 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- CF9AFCBF84244C1D44C2E795 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
- E1DF330ADC8450B8B567025E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -54,30 +62,18 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 127B2300FA5CE87549434CC2 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
- 13FB0627975E846BA76A343C /* Pods */ = {
+ 331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
- CF9AFCBF84244C1D44C2E795 /* Pods-Runner.debug.xcconfig */,
- 4928082F7E2BC0BADA4A6955 /* Pods-Runner.release.xcconfig */,
- E1DF330ADC8450B8B567025E /* Pods-Runner.profile.xcconfig */,
+ 331C807B294A618700263BE5 /* RunnerTests.swift */,
);
- name = Pods;
- path = Pods;
- sourceTree = "";
- };
- 1DB0744A0D67D7FBC7C14ADA /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- 3A72EECE5117AE803156E244 /* Pods_Runner.framework */,
- );
- name = Frameworks;
+ path = RunnerTests;
sourceTree = "";
};
9740EEB11CF90186004384FC /* Flutter */ = {
@@ -97,8 +93,7 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
- 13FB0627975E846BA76A343C /* Pods */,
- 1DB0744A0D67D7FBC7C14ADA /* Frameworks */,
+ 331C8082294A63A400263BE5 /* RunnerTests */,
);
sourceTree = "";
};
@@ -106,6 +101,7 @@
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
+ 331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "";
@@ -128,18 +124,33 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
+ 331C8080294A63A400263BE5 /* RunnerTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
+ buildPhases = (
+ 331C807D294A63A400263BE5 /* Sources */,
+ 331C807F294A63A400263BE5 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 331C8086294A63A400263BE5 /* PBXTargetDependency */,
+ );
+ name = RunnerTests;
+ productName = RunnerTests;
+ productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
- 2655651DCB6AEB0882B90CC1 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
- C1C85694F6D3CCB2E45E23F9 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -156,9 +167,14 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1020;
+ BuildIndependentTargetsInParallel = YES;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
+ 331C8080294A63A400263BE5 = {
+ CreatedOnToolsVersion = 14.0;
+ TestTargetID = 97C146ED1CF9000F007C117D;
+ };
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
@@ -179,11 +195,19 @@
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
+ 331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
+ 331C807F294A63A400263BE5 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -198,34 +222,14 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
- 2655651DCB6AEB0882B90CC1 /* [CP] Check Pods Manifest.lock */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- );
- inputPaths = (
- "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
- "${PODS_ROOT}/Manifest.lock",
- );
- name = "[CP] Check Pods Manifest.lock";
- outputFileListPaths = (
- );
- outputPaths = (
- "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
- showEnvVarsInLog = 0;
- };
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -236,6 +240,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -248,26 +253,17 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
- C1C85694F6D3CCB2E45E23F9 /* [CP] Embed Pods Frameworks */ = {
- isa = PBXShellScriptBuildPhase;
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 331C807D294A63A400263BE5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- );
- inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
- );
- name = "[CP] Embed Pods Frameworks";
- outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
- showEnvVarsInLog = 0;
};
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -279,6 +275,14 @@
};
/* End PBXSourcesBuildPhase section */
+/* Begin PBXTargetDependency section */
+ 331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 97C146ED1CF9000F007C117D /* Runner */;
+ targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
@@ -303,6 +307,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@@ -332,6 +337,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -340,7 +346,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -358,8 +364,11 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = me.jpryan.flutterMapExample;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = dev.fleaflet.fluttermap.flutterMapExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -367,10 +376,58 @@
};
name = Profile;
};
+ 331C8088294A63A400263BE5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = dev.fleaflet.fluttermap.flutterMapExample.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Debug;
+ };
+ 331C8089294A63A400263BE5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = dev.fleaflet.fluttermap.flutterMapExample.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Release;
+ };
+ 331C808A294A63A400263BE5 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = dev.fleaflet.fluttermap.flutterMapExample.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
+ };
+ name = Profile;
+ };
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@@ -400,6 +457,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -414,7 +472,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -426,6 +484,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@@ -455,6 +514,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -463,11 +523,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -482,8 +543,11 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = me.jpryan.flutterMapExample;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = dev.fleaflet.fluttermap.flutterMapExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -501,8 +565,11 @@
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = me.jpryan.flutterMapExample;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = dev.fleaflet.fluttermap.flutterMapExample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -513,6 +580,16 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 331C8088294A63A400263BE5 /* Debug */,
+ 331C8089294A63A400263BE5 /* Release */,
+ 331C808A294A63A400263BE5 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index a28140cfd..e3773d42e 100644
--- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
-
-
-
-
+
+
+
+
+
+
@@ -61,8 +73,6 @@
ReferencedContainer = "container:Runner.xcodeproj">
-
-
-
-
diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift
index 70693e4a8..626664468 100644
--- a/example/ios/Runner/AppDelegate.swift
+++ b/example/ios/Runner/AppDelegate.swift
@@ -1,7 +1,7 @@
-import UIKit
import Flutter
+import UIKit
-@UIApplicationMain
+@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png
deleted file mode 100644
index 861963cda..000000000
Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png and /dev/null differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png
deleted file mode 100644
index 0d83bfc31..000000000
Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png and /dev/null differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png
deleted file mode 100644
index 7ef45797d..000000000
Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png and /dev/null differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png
deleted file mode 100644
index fd1f03a7b..000000000
Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png and /dev/null differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png
deleted file mode 100644
index d48a9b98d..000000000
Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png and /dev/null differ
diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png
deleted file mode 100644
index 980d106b5..000000000
Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png and /dev/null differ
diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist
index 7f2c8fc99..7680919e1 100644
--- a/example/ios/Runner/Info.plist
+++ b/example/ios/Runner/Info.plist
@@ -4,6 +4,8 @@
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ flutter_map Demo
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
@@ -39,7 +41,9 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
- UIViewControllerBasedStatusBarAppearance
-
+ CADisableMinimumFrameDurationOnPhone
+
+ UIApplicationSupportsIndirectInputEvents
+
diff --git a/example/ios/RunnerTests/RunnerTests.swift b/example/ios/RunnerTests/RunnerTests.swift
new file mode 100644
index 000000000..86a7c3b1b
--- /dev/null
+++ b/example/ios/RunnerTests/RunnerTests.swift
@@ -0,0 +1,12 @@
+import Flutter
+import UIKit
+import XCTest
+
+class RunnerTests: XCTestCase {
+
+ func testExample() {
+ // If you add code to the Runner application, consider adding tests here.
+ // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
+ }
+
+}
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 4eb4d17f2..ab778424d 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -9,6 +9,7 @@ import 'package:flutter_map_example/pages/epsg4326_crs.dart';
import 'package:flutter_map_example/pages/fallback_url_page.dart';
import 'package:flutter_map_example/pages/home.dart';
import 'package:flutter_map_example/pages/interactive_test_page.dart';
+import 'package:flutter_map_example/pages/inverted_polygons.dart';
import 'package:flutter_map_example/pages/latlng_to_screen_point.dart';
import 'package:flutter_map_example/pages/many_circles.dart';
import 'package:flutter_map_example/pages/many_markers.dart';
@@ -68,6 +69,7 @@ class MyApp extends StatelessWidget {
OverlayImagePage.route: (context) => const OverlayImagePage(),
PolygonPage.route: (context) => const PolygonPage(),
MultiWorldsPage.route: (context) => const MultiWorldsPage(),
+ InvertedPolygonsPage.route: (context) => const InvertedPolygonsPage(),
PolygonPerfStressPage.route: (context) => const PolygonPerfStressPage(),
SlidingMapPage.route: (_) => const SlidingMapPage(),
WMSLayerPage.route: (context) => const WMSLayerPage(),
diff --git a/example/lib/pages/inverted_polygons.dart b/example/lib/pages/inverted_polygons.dart
new file mode 100644
index 000000000..b030ecfb2
--- /dev/null
+++ b/example/lib/pages/inverted_polygons.dart
@@ -0,0 +1,134 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_map/flutter_map.dart';
+import 'package:flutter_map_example/misc/tile_providers.dart';
+import 'package:flutter_map_example/widgets/drawer/menu_drawer.dart';
+import 'package:latlong2/latlong.dart';
+
+/// Example dedicated to [PolygonLayer.invertedFill]
+class InvertedPolygonsPage extends StatefulWidget {
+ static const String route = '/inverted_polygons';
+
+ const InvertedPolygonsPage({super.key});
+
+ @override
+ State createState() => _InvertedPolygonsPageState();
+}
+
+class _InvertedPolygonsPageState extends State {
+ final LayerHitNotifier _hitNotifier = ValueNotifier(null);
+
+ final _customMarkers = [];
+
+ Marker _buildPin(LatLng point) => Marker(
+ point: point,
+ width: 60,
+ height: 60,
+ child: GestureDetector(
+ onTap: () => ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(
+ content: Text('Tapped existing marker'),
+ duration: Duration(seconds: 1),
+ showCloseIcon: true,
+ ),
+ ),
+ child: const Icon(Icons.location_pin, color: Colors.red),
+ ),
+ );
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Advanced polygons')),
+ drawer: const MenuDrawer(InvertedPolygonsPage.route),
+ body: Stack(
+ children: [
+ FlutterMap(
+ options: MapOptions(
+ initialCenter: const LatLng(45.5, 2),
+ initialZoom: 0,
+ initialRotation: 0,
+ onTap: (_, p) => setState(() => _customMarkers.add(_buildPin(p))),
+ ),
+ children: [
+ openStreetMapTileLayer,
+ GestureDetector(
+ onTap: () => ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(_hitNotifier.value!.hitValues.join(', ')),
+ duration: const Duration(seconds: 1),
+ showCloseIcon: true,
+ ),
+ ),
+ child: PolygonLayer(
+ hitNotifier: _hitNotifier,
+ simplificationTolerance: 0,
+ useAltRendering: false,
+ drawLabelsLast: false,
+ invertedFill: const Color(0x20FF0000),
+ polygons: [
+ Polygon(
+ rotateLabel: false,
+ borderColor: const Color(0xFF0000FF),
+ borderStrokeWidth: 3,
+ color: const Color(0x4000FFFF),
+ hitValue: 'France',
+ points: const [
+ // France
+ // Calais 50° 56′ 53″ nord, 1° 51′ 23″ est
+ LatLng(50.948056, 1.856389),
+ // Brest 48° 23′ 27″ nord, 4° 29′ 08″ ouest
+ LatLng(48.390833, -4.485556),
+ // Biarritz 43° 28′ 54″ nord, 1° 33′ 22″ ouest
+ LatLng(43.481667, -1.556111),
+ // Perpignan 42° 41′ 55″ nord, 2° 53′ 44″ est
+ LatLng(42.698611, 2.895556),
+ // Menton 43° 46′ 33″ nord, 7° 30′ 10″ est
+ LatLng(43.775833, 7.502778),
+ // Strasbourg 48° 34′ 24″ nord, 7° 45′ 08″ est
+ LatLng(48.573333, 7.752222),
+ ],
+ ),
+ Polygon(
+ rotateLabel: false,
+ borderColor: const Color(0xFFFF0000),
+ borderStrokeWidth: 3,
+ pattern: StrokePattern.dashed(segments: [20, 10, 10, 10]),
+ color: null,
+ hitValue: 'South America',
+ points: const [
+ // South America
+ // Ushuaia 54° 48′ 35″ sud, 68° 18′ 50″ ouest
+ LatLng(-54.809722, -68.313889),
+ // Fortaleza 3° 43′ 01″ sud, 38° 32′ 34″ ouest
+ LatLng(-3.716944, -38.542778),
+ // Panama 8° 58′ nord, 79° 32′ ouest
+ LatLng(8.966667, -79.533333),
+ // Quito 0° 14′ 18″ sud, 78° 31′ 02″ ouest
+ LatLng(-0.238333, -78.517222),
+ ],
+ ),
+ Polygon(
+ rotateLabel: false,
+ borderColor: const Color(0xFF00FF00),
+ borderStrokeWidth: 3,
+ pattern: const StrokePattern.dotted(spacingFactor: 3),
+ color: const Color(0x20000000),
+ hitValue: 'Across the border',
+ points: const [
+ // Across the border
+ LatLng(26.69, -137.39),
+ LatLng(37.91, 150.65),
+ LatLng(-7.67, 151.20),
+ LatLng(-7.32, -140.78),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/example/lib/pages/polygon.dart b/example/lib/pages/polygon.dart
index 02717514e..02f646041 100644
--- a/example/lib/pages/polygon.dart
+++ b/example/lib/pages/polygon.dart
@@ -4,6 +4,7 @@ import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_example/misc/tile_providers.dart';
import 'package:flutter_map_example/widgets/drawer/menu_drawer.dart';
import 'package:latlong2/latlong.dart';
+import 'package:url_launcher/url_launcher.dart';
typedef HitValue = ({String title, String subtitle});
@@ -21,6 +22,8 @@ class _PolygonPageState extends State {
List? _prevHitValues;
List>? _hoverGons;
+ bool _useInvertedFill = false;
+
final _polygonsRaw = >[
Polygon(
points: const [
@@ -108,27 +111,26 @@ class _PolygonPageState extends State {
pattern: const StrokePattern.dotted(),
holePointsList: [
const [
- LatLng(52, -17),
- LatLng(52, -16),
- LatLng(51.5, -15.5),
- LatLng(51, -16),
- LatLng(51, -17),
+ LatLng(52, -9),
+ LatLng(52, -8),
+ LatLng(51.5, -7.5),
+ LatLng(51, -8),
+ LatLng(51, -9),
],
const [
- LatLng(53.5, -17),
- LatLng(53.5, -16),
- LatLng(53, -15),
- LatLng(52.25, -15),
- LatLng(52.25, -16),
- LatLng(52.75, -17),
+ LatLng(53.5, -9),
+ LatLng(53.5, -8),
+ LatLng(53, -7),
+ LatLng(52.25, -7),
+ LatLng(52.25, -8),
+ LatLng(52.75, -9),
],
- ]
- .map(
- (latlngs) => latlngs
- .map((latlng) => LatLng(latlng.latitude, latlng.longitude + 8))
- .toList(),
- )
- .toList(),
+ const [
+ LatLng(52.683614, -8.141285),
+ LatLng(51.663083, -8.684529),
+ LatLng(51.913924, -7.2193),
+ ],
+ ],
borderStrokeWidth: 4,
borderColor: Colors.orange,
color: Colors.orange.withAlpha(128),
@@ -154,30 +156,26 @@ class _PolygonPageState extends State {
pattern: const StrokePattern.dotted(),
holePointsList: [
const [
- LatLng(52, -17),
- LatLng(52, -16),
- LatLng(51.5, -15.5),
- LatLng(51, -16),
- LatLng(51, -17),
- ],
+ LatLng(46, -9),
+ LatLng(46, -8),
+ LatLng(45.5, -7.5),
+ LatLng(45, -8),
+ LatLng(45, -9),
+ ].reversed.toList(growable: false), // Testing winding consitency
const [
- LatLng(53.5, -17),
- LatLng(53.5, -16),
- LatLng(53, -15),
- LatLng(52.25, -15),
- LatLng(52.25, -16),
- LatLng(52.75, -17),
- ],
- ]
- .map(
- (latlngs) => latlngs
- .map((latlng) =>
- LatLng(latlng.latitude - 6, latlng.longitude + 8))
- .toList()
- .reversed // Test that holes are always cut, no matter winding
- .toList(),
- )
- .toList(),
+ LatLng(47.5, -9),
+ LatLng(47.5, -8),
+ LatLng(47, -7),
+ LatLng(46.25, -7),
+ LatLng(46.25, -8),
+ LatLng(46.75, -9),
+ ].reversed.toList(growable: false),
+ const [
+ LatLng(46.683614, -8.141285),
+ LatLng(45.663083, -8.684529),
+ LatLng(45.913924, -7.2193),
+ ].reversed.toList(growable: false),
+ ],
borderStrokeWidth: 4,
borderColor: Colors.orange,
color: Colors.orange.withAlpha(128),
@@ -255,6 +253,35 @@ class _PolygonPageState extends State {
"Holes shouldn't be cut, and colors should be mixed correctly",
),
),
+ Polygon(
+ points: const [
+ LatLng(40, 150),
+ LatLng(45, 160),
+ LatLng(50, 170),
+ LatLng(55, 180),
+ LatLng(50, -170),
+ LatLng(45, -160),
+ LatLng(40, -150),
+ LatLng(35, -160),
+ LatLng(30, -170),
+ LatLng(25, -180),
+ LatLng(30, 170),
+ LatLng(35, 160),
+ ],
+ holePointsList: const [
+ [
+ LatLng(45, 175),
+ LatLng(45, -175),
+ LatLng(35, -175),
+ LatLng(35, 175),
+ ],
+ ],
+ color: const Color(0xFFFF0000),
+ hitValue: (
+ title: 'Red Line',
+ subtitle: 'Across the universe...',
+ ),
+ ),
];
late final _polygons =
Map.fromEntries(_polygonsRaw.map((e) => MapEntry(e.hitValue, e)));
@@ -268,7 +295,7 @@ class _PolygonPageState extends State {
children: [
FlutterMap(
options: const MapOptions(
- initialCenter: LatLng(51.5, -0.09),
+ initialCenter: LatLng(51.5, -2),
initialZoom: 5,
),
children: [
@@ -320,6 +347,8 @@ class _PolygonPageState extends State {
child: PolygonLayer(
hitNotifier: _hitNotifier,
simplificationTolerance: 0,
+ invertedFill:
+ _useInvertedFill ? Colors.pink.withAlpha(170) : null,
polygons: [..._polygonsRaw, ...?_hoverGons],
),
),
@@ -328,35 +357,6 @@ class _PolygonPageState extends State {
simplificationTolerance: 0,
useAltRendering: true,
polygons: [
- Polygon(
- points: const [
- LatLng(40, 150),
- LatLng(45, 160),
- LatLng(50, 170),
- LatLng(55, 180),
- LatLng(50, -170),
- LatLng(45, -160),
- LatLng(40, -150),
- LatLng(35, -160),
- LatLng(30, -170),
- LatLng(25, -180),
- LatLng(30, 170),
- LatLng(35, 160),
- ],
- holePointsList: const [
- [
- LatLng(45, 175),
- LatLng(45, -175),
- LatLng(35, -175),
- LatLng(35, 175),
- ],
- ],
- color: const Color(0xFFFF0000),
- hitValue: (
- title: 'Red Line',
- subtitle: 'Across the universe...',
- ),
- ),
Polygon(
points: const [
LatLng(50, -18),
@@ -385,50 +385,117 @@ class _PolygonPageState extends State {
borderStrokeWidth: 4,
borderColor: Colors.black,
color: Colors.green,
+ label:
+ 'This one is performantly rendered\n& non-interactive',
),
Polygon(
points: const [
- LatLng(50, -18),
- LatLng(53, -16),
- LatLng(51.5, -12.5),
- LatLng(54, -14),
- LatLng(54, -18),
- ]
- .map((latlng) =>
- LatLng(latlng.latitude - 6, latlng.longitude))
- .toList(),
+ LatLng(44, -18),
+ LatLng(47, -16),
+ LatLng(45.5, -12.5),
+ LatLng(48, -14),
+ LatLng(48, -18),
+ ],
holePointsList: [
const [
- LatLng(52, -17),
- LatLng(52, -16),
- LatLng(51.5, -15.5),
- LatLng(51, -16),
- LatLng(51, -17),
+ LatLng(46, -17),
+ LatLng(46, -16),
+ LatLng(45.5, -15.5),
+ LatLng(45, -16),
+ LatLng(45, -17),
],
const [
- LatLng(53.5, -17),
- LatLng(53.5, -16),
- LatLng(53, -15),
- LatLng(52.25, -15),
- LatLng(52.25, -16),
- LatLng(52.75, -17),
+ LatLng(47.5, -17),
+ LatLng(47.5, -16),
+ LatLng(47, -15),
+ LatLng(46.25, -15),
+ LatLng(46.25, -16),
+ LatLng(46.75, -17),
],
- ]
- .map(
- (latlngs) => latlngs
- .map((latlng) =>
- LatLng(latlng.latitude - 6, latlng.longitude))
- .toList(),
- )
- .toList(),
+ const [
+ LatLng(46.683614, -16.141285),
+ LatLng(45.663083, -16.684529),
+ LatLng(45.913924, -15.2193),
+ ].reversed.toList(growable: false),
+ ],
borderStrokeWidth: 4,
borderColor: Colors.black,
color: Colors.green,
+ label:
+ "Performant-rendering doesn't\nhandle malformed polygons",
),
],
),
],
),
+ Positioned(
+ top: 16,
+ right: 16,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(kIsWeb ? 16 : 32),
+ child: ColoredBox(
+ color: Theme.of(context).colorScheme.surface,
+ child: Column(
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(
+ left: 12,
+ right: 8,
+ top: 4,
+ bottom: 4,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ spacing: 8,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ const Tooltip(
+ message: 'Use Inverted Fill',
+ child: Icon(Icons.invert_colors),
+ ),
+ Switch.adaptive(
+ value: _useInvertedFill,
+ onChanged: (v) =>
+ setState(() => _useInvertedFill = v),
+ ),
+ ],
+ ),
+ ),
+ if (kIsWeb)
+ ColoredBox(
+ color: Colors.amber,
+ child: Padding(
+ padding: const EdgeInsets.only(
+ left: 16,
+ right: 16,
+ top: 6,
+ bottom: 6,
+ ),
+ child: Row(
+ mainAxisSize: MainAxisSize.min,
+ spacing: 8,
+ children: [
+ const Icon(Icons.warning),
+ const Icon(Icons.web_asset_off),
+ IconButton(
+ onPressed: () => launchUrl(Uri.parse(
+ 'https://docs.fleaflet.dev/layers/polygon-layer#inverted-filling',
+ )),
+ style: ButtonStyle(
+ backgroundColor:
+ WidgetStatePropertyAll(Colors.amber[100]),
+ ),
+ icon: const Icon(Icons.open_in_new),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
],
),
);
diff --git a/example/lib/widgets/drawer/menu_drawer.dart b/example/lib/widgets/drawer/menu_drawer.dart
index 5d130c072..ad6563476 100644
--- a/example/lib/widgets/drawer/menu_drawer.dart
+++ b/example/lib/widgets/drawer/menu_drawer.dart
@@ -10,6 +10,7 @@ import 'package:flutter_map_example/pages/epsg4326_crs.dart';
import 'package:flutter_map_example/pages/fallback_url_page.dart';
import 'package:flutter_map_example/pages/home.dart';
import 'package:flutter_map_example/pages/interactive_test_page.dart';
+import 'package:flutter_map_example/pages/inverted_polygons.dart';
import 'package:flutter_map_example/pages/latlng_to_screen_point.dart';
import 'package:flutter_map_example/pages/many_circles.dart';
import 'package:flutter_map_example/pages/many_markers.dart';
@@ -178,6 +179,11 @@ class MenuDrawer extends StatelessWidget {
routeName: ManyCirclesPage.route,
currentRoute: currentRoute,
),
+ MenuItemWidget(
+ caption: 'Inverted Polygons',
+ routeName: InvertedPolygonsPage.route,
+ currentRoute: currentRoute,
+ ),
const Divider(),
MenuItemWidget(
caption: 'Zoom Buttons Plugin',
diff --git a/lib/src/layer/polygon_layer/painter.dart b/lib/src/layer/polygon_layer/painter.dart
index bbfbea9a0..8406fa299 100644
--- a/lib/src/layer/polygon_layer/painter.dart
+++ b/lib/src/layer/polygon_layer/painter.dart
@@ -8,6 +8,9 @@ class _PolygonPainter extends CustomPainter
/// Reference to the list of [_ProjectedPolygon]s
final List<_ProjectedPolygon> polygons;
+ @override
+ Iterable<_ProjectedPolygon> get elements => polygons;
+
/// Triangulated [polygons] if available
///
/// Expected to be in same/corresponding order as [polygons].
@@ -35,6 +38,9 @@ class _PolygonPainter extends CustomPainter
/// See [PolygonLayer.debugAltRenderer]
final bool debugAltRenderer;
+ /// See [PolygonLayer.invertedFill]
+ final Color? invertedFill;
+
@override
final MapCamera camera;
@@ -49,9 +55,41 @@ class _PolygonPainter extends CustomPainter
required this.drawLabelsLast,
required this.debugAltRenderer,
required this.camera,
+ required this.invertedFill,
required this.hitNotifier,
}) : bounds = camera.visibleBounds;
+ /// Corner coordinates of the polygon painted onto the entire world when using
+ /// inverted fill.
+ static const _minMaxLatitude = [LatLng(90, 0), LatLng(-90, 0)];
+
+ /// Whether to use `PathFillType.evenOdd` (true) or `Path.combine` (false).
+ ///
+ /// * `Path.combine` doesn't work & isn't stable/consistent on web
+ /// * `evenOdd` gives broken results when polygons intersect when inverted
+ /// * `Path.combine` has slightly worse performance than `evenOdd`
+ ///
+ /// The best option is to use `evenOdd` on web, as it at least works
+ /// sometimes. On native, we use `Path.combine` when inverted filling, or
+ /// `evenOdd` otherwise.
+ ///
+ /// See https://github.com/fleaflet/flutter_map/pull/2046.
+ late final _useEvenOdd = kIsWeb || invertedFill == null;
+
+ /// Do we also remove the holes from the inverted map?
+ /// Should be `true`.
+ static const _invertedHoles = true;
+
+ /// Do we also fill the holes with inverted fill?
+ /// Should be `true`.
+ static const _fillInvertedHoles = true;
+
+ /// Whether to draw the batch of polygons when a polygon with translucency is
+ /// encountered.
+ /// Should be `true`.
+ // TODO: Verify if still necessary.
+ static const _flushBatchOnTranslucency = true;
+
@override
bool elementHitTest(
_ProjectedPolygon projectedPolygon, {
@@ -112,101 +150,103 @@ class _PolygonPainter extends CustomPainter
return workAcrossWorlds(checkIfHit);
}
- @override
- Iterable<_ProjectedPolygon> get elements => polygons;
-
@override
void paint(Canvas canvas, Size size) {
- const checkOpacity = true; // for debugging purposes only, should be true
super.paint(canvas, size);
final trianglePoints = [];
- final filledPath = Path();
+ Path filledPath = Path();
+ Path invertedHolePaths = Path();
final borderPath = Path();
- Polygon? lastPolygon;
+ Color? lastColor;
int? lastHash;
+ Paint? borderPaint;
+
+ /// Draw polygon outline
+ void drawBorders() {
+ if (borderPaint != null) {
+ canvas.drawPath(borderPath, borderPaint);
+ }
+ borderPath.reset();
+ lastHash = null;
+ }
// This functions flushes the batched fill and border paths constructed below
void drawPaths() {
- if (lastPolygon == null) return;
- final polygon = lastPolygon!;
+ final Color? color = lastColor;
+ if (color == null) {
+ drawBorders();
+ return;
+ }
// Draw filled polygon
- if (polygon.color case final color?) {
- final paint = Paint()
- ..style = PaintingStyle.fill
- ..color = color;
-
- if (trianglePoints.isNotEmpty) {
- final points = Float32List(trianglePoints.length * 2);
- for (int i = 0; i < trianglePoints.length; ++i) {
- points[i * 2] = trianglePoints[i].dx;
- points[i * 2 + 1] = trianglePoints[i].dy;
- }
- final vertices = Vertices.raw(VertexMode.triangles, points);
- canvas.drawVertices(vertices, BlendMode.src, paint);
-
- if (debugAltRenderer) {
- for (int i = 0; i < trianglePoints.length; i += 3) {
- canvas.drawCircle(
- trianglePoints[i],
- 5,
- Paint()..color = const Color(0x7EFF0000),
- );
- canvas.drawCircle(
- trianglePoints[i + 1],
- 5,
- Paint()..color = const Color(0x7E00FF00),
- );
- canvas.drawCircle(
- trianglePoints[i + 2],
- 5,
- Paint()..color = const Color(0x7E0000FF),
- );
+ final paint = Paint()
+ ..style = PaintingStyle.fill
+ ..color = color;
+
+ if (trianglePoints.isNotEmpty) {
+ final points = Float32List(trianglePoints.length * 2);
+ for (int i = 0; i < trianglePoints.length; ++i) {
+ points[i * 2] = trianglePoints[i].dx;
+ points[i * 2 + 1] = trianglePoints[i].dy;
+ }
+ final vertices = Vertices.raw(VertexMode.triangles, points);
+ canvas.drawVertices(vertices, BlendMode.src, paint);
- final path = Path()
- ..addPolygon(
- [
- trianglePoints[i],
- trianglePoints[i + 1],
- trianglePoints[i + 2],
- ],
- true,
- );
-
- canvas.drawPath(
- path,
- Paint()
- ..color = const Color(0x7EFFFFFF)
- ..style = PaintingStyle.fill,
- );
+ if (debugAltRenderer) {
+ for (int i = 0; i < trianglePoints.length; i += 3) {
+ canvas.drawCircle(
+ trianglePoints[i],
+ 5,
+ Paint()..color = const Color(0x7EFF0000),
+ );
+ canvas.drawCircle(
+ trianglePoints[i + 1],
+ 5,
+ Paint()..color = const Color(0x7E00FF00),
+ );
+ canvas.drawCircle(
+ trianglePoints[i + 2],
+ 5,
+ Paint()..color = const Color(0x7E0000FF),
+ );
- canvas.drawPath(
- path,
- Paint()
- ..color = const Color(0xFF000000)
- ..style = PaintingStyle.stroke,
+ final path = Path()
+ ..addPolygon(
+ [
+ trianglePoints[i],
+ trianglePoints[i + 1],
+ trianglePoints[i + 2],
+ ],
+ true,
);
- }
+
+ canvas.drawPath(
+ path,
+ Paint()
+ ..color = const Color(0x7EFFFFFF)
+ ..style = PaintingStyle.fill,
+ );
+
+ canvas.drawPath(
+ path,
+ Paint()
+ ..color = const Color(0xFF000000)
+ ..style = PaintingStyle.stroke,
+ );
}
- } else {
- canvas.drawPath(filledPath, paint);
}
- }
-
- // Draw polygon outline
- if (polygon.borderStrokeWidth > 0) {
- canvas.drawPath(borderPath, _getBorderPaint(polygon));
+ } else {
+ canvas.drawPath(filledPath, paint);
}
trianglePoints.clear();
filledPath.reset();
- borderPath.reset();
+ lastColor = null;
- lastPolygon = null;
- lastHash = null;
+ drawBorders();
}
/// Draws labels on a "single-world"
@@ -238,11 +278,106 @@ class _PolygonPainter extends CustomPainter
return WorldWorkControl.visible;
}
- // Main loop constructing batched fill and border paths from given polygons.
+ void invertFillPolygonHole(List offsets) {
+ // For debugging purposes, should be compiled out
+ // ignore: dead_code
+ if (!_fillInvertedHoles) return;
+
+ if (_useEvenOdd) {
+ invertedHolePaths.addPolygon(offsets, true);
+ return;
+ }
+ invertedHolePaths = Path.combine(
+ PathOperation.union,
+ invertedHolePaths,
+ Path()..addPolygon(offsets, true),
+ );
+ }
+
+ void unfillPolygon(List offsets) {
+ if (_useEvenOdd) {
+ filledPath.fillType = PathFillType.evenOdd;
+ filledPath.addPolygon(offsets, true);
+ return;
+ }
+ filledPath = Path.combine(
+ PathOperation.difference,
+ filledPath,
+ Path()..addPolygon(offsets, true),
+ );
+ }
+
+ // Specific map treatment with `invertFill`.
+ if (invertedFill != null) {
+ filledPath.reset();
+ final minMaxProjected =
+ camera.crs.projection.projectList(_minMaxLatitude);
+ final minMaxY = getOffsetsXY(
+ camera: camera,
+ origin: origin,
+ points: minMaxProjected,
+ );
+ final maxX = viewportRect.right;
+ final minX = viewportRect.left;
+ final maxY = minMaxY[0].dy;
+ final minY = minMaxY[1].dy;
+ final rect = Rect.fromLTRB(minX, minY, maxX, maxY);
+ filledPath.addRect(rect);
+
+ for (int i = 0; i <= polygons.length - 1; i++) {
+ final projectedPolygon = polygons[i];
+ if (projectedPolygon.points.isEmpty) continue;
+
+ /// Draws each full polygon as a hole on a "single-world"
+ WorldWorkControl drawPolygonAsHole(double shift) {
+ final fillOffsets = getOffsetsXY(
+ camera: camera,
+ origin: origin,
+ points: projectedPolygon.points,
+ shift: shift,
+ );
+ if (!areOffsetsVisible(fillOffsets)) {
+ return WorldWorkControl.invisible;
+ }
+
+ unfillPolygon(fillOffsets);
+
+ if (_invertedHoles) {
+ for (final singleHolePoints in projectedPolygon.holePoints) {
+ final holeOffsets = getOffsetsXY(
+ camera: camera,
+ origin: origin,
+ points: singleHolePoints,
+ shift: shift,
+ );
+ unfillPolygon(holeOffsets);
+ invertFillPolygonHole(holeOffsets);
+ }
+ }
+ return WorldWorkControl.visible;
+ }
+
+ workAcrossWorlds(drawPolygonAsHole);
+ }
+
+ // Draw filled map with polygons as holes
+ final paint = Paint()
+ ..style = PaintingStyle.fill
+ ..color = invertedFill!;
+
+ canvas.drawPath(filledPath, paint);
+ if (_fillInvertedHoles) {
+ canvas.drawPath(invertedHolePaths, paint);
+ }
+
+ filledPath.reset();
+ }
+
for (int i = 0; i <= polygons.length - 1; i++) {
final projectedPolygon = polygons[i];
- if (projectedPolygon.points.isEmpty) continue;
final polygon = projectedPolygon.polygon;
+ if (projectedPolygon.points.isEmpty) continue;
+ borderPaint = _getBorderPaint(polygon);
final polygonTriangles = triangles?[i];
@@ -256,7 +391,9 @@ class _PolygonPainter extends CustomPainter
polygonTriangles != null ? projectedPolygon.holePoints : null,
shift: shift,
);
- if (!areOffsetsVisible(fillOffsets)) return WorldWorkControl.invisible;
+ if (!areOffsetsVisible(fillOffsets)) {
+ return WorldWorkControl.invisible;
+ }
if (debugAltRenderer) {
const offsetsLabelStyle = TextStyle(
@@ -285,10 +422,11 @@ class _PolygonPainter extends CustomPainter
// depending on the holes handler.
final hash = polygon.renderHashCode;
final opacity = polygon.color?.a ?? 0;
- if (lastHash != hash || (checkOpacity && opacity > 0 && opacity < 1)) {
+ if (lastHash != hash ||
+ (_flushBatchOnTranslucency && opacity > 0 && opacity < 1)) {
drawPaths();
}
- lastPolygon = polygon;
+ lastColor = polygon.color;
lastHash = hash;
// First add fills and borders to path.
@@ -303,20 +441,23 @@ class _PolygonPainter extends CustomPainter
}
}
- if (polygon.borderStrokeWidth > 0.0) {
- _addBorderToPath(
- borderPath,
- polygon,
+ void addBorderToPath(List offsets) => _addBorderToPath(
+ borderPath,
+ polygon,
+ offsets,
+ size,
+ canvas,
+ borderPaint!,
+ );
+
+ if (borderPaint != null) {
+ addBorderToPath(
getOffsetsXY(
camera: camera,
origin: origin,
points: projectedPolygon.points,
shift: shift,
),
- size,
- canvas,
- _getBorderPaint(polygon),
- polygon.borderStrokeWidth,
);
}
@@ -324,52 +465,16 @@ class _PolygonPainter extends CustomPainter
// Improper handling of opacity and fill methods may result in normal
// polygons cutting holes into other polygons, when they should be mixing:
// https://github.com/fleaflet/flutter_map/issues/1898.
- final holePointsList = polygon.holePointsList;
- if (holePointsList != null && holePointsList.isNotEmpty) {
- // See `Path.combine` comments below
- // Avoids failing to cut holes if the winding directions of the holes
- // and the normal points are the same
- filledPath.fillType = PathFillType.evenOdd;
-
- for (final singleHolePoints in projectedPolygon.holePoints) {
- final holeOffsets = getOffsetsXY(
- camera: camera,
- origin: origin,
- points: singleHolePoints,
- shift: shift,
- );
- filledPath.addPolygon(holeOffsets, true);
-
- // TODO: Potentially more efficient and may change the need to do
- // opacity checking - needs testing. Also need to verify if `xor` or
- // `difference` is preferred.
- // No longer blocked by lack of HTML support in Flutter 3.29
- /*filledPath = Path.combine(
- PathOperation.xor,
- filledPath,
- Path()..addPolygon(holeOffsets, true),
- );*/
- }
-
- if (!polygon.disableHolesBorder && polygon.borderStrokeWidth > 0.0) {
- final borderPaint = _getBorderPaint(polygon);
- for (final singleHolePoints in projectedPolygon.holePoints) {
- final holeOffsets = getOffsetsXY(
- camera: camera,
- origin: origin,
- points: singleHolePoints,
- shift: shift,
- );
- _addBorderToPath(
- borderPath,
- polygon,
- holeOffsets,
- size,
- canvas,
- borderPaint,
- polygon.borderStrokeWidth,
- );
- }
+ for (final singleHolePoints in projectedPolygon.holePoints) {
+ final holeOffsets = getOffsetsXY(
+ camera: camera,
+ origin: origin,
+ points: singleHolePoints,
+ shift: shift,
+ );
+ unfillPolygon(holeOffsets);
+ if (!polygon.disableHolesBorder && borderPaint != null) {
+ addBorderToPath(holeOffsets);
}
}
@@ -392,10 +497,9 @@ class _PolygonPainter extends CustomPainter
(double shift) => drawLabelIfVisible(shift, projectedPolygon),
);
}
+ drawPaths();
}
- drawPaths();
-
if (polygonLabels && drawLabelsLast) {
for (final projectedPolygon in polygons) {
if (projectedPolygon.points.isEmpty) {
@@ -411,7 +515,10 @@ class _PolygonPainter extends CustomPainter
}
}
- Paint _getBorderPaint(Polygon polygon) {
+ Paint? _getBorderPaint(Polygon polygon) {
+ if (polygon.borderStrokeWidth <= 0) {
+ return null;
+ }
final isDotted = polygon.pattern.spacingFactor != null;
return Paint()
..color = polygon.borderColor
@@ -428,11 +535,11 @@ class _PolygonPainter extends CustomPainter
Size canvasSize,
Canvas canvas,
Paint paint,
- double strokeWidth,
) {
final isSolid = polygon.pattern == const StrokePattern.solid();
final isDashed = polygon.pattern.segments != null;
final isDotted = polygon.pattern.spacingFactor != null;
+ final strokeWidth = polygon.borderStrokeWidth;
if (isSolid) {
final SolidPixelHiker hiker = SolidPixelHiker(
@@ -445,7 +552,7 @@ class _PolygonPainter extends CustomPainter
} else if (isDotted) {
final DottedPixelHiker hiker = DottedPixelHiker(
offsets: offsets,
- stepLength: polygon.borderStrokeWidth * polygon.pattern.spacingFactor!,
+ stepLength: strokeWidth * polygon.pattern.spacingFactor!,
patternFit: polygon.pattern.patternFit!,
closePath: true,
canvasSize: canvasSize,
@@ -485,6 +592,7 @@ class _PolygonPainter extends CustomPainter
triangles != oldDelegate.triangles ||
camera != oldDelegate.camera ||
bounds != oldDelegate.bounds ||
+ invertedFill != oldDelegate.invertedFill ||
drawLabelsLast != oldDelegate.drawLabelsLast ||
polygonLabels != oldDelegate.polygonLabels ||
hitNotifier != oldDelegate.hitNotifier;
diff --git a/lib/src/layer/polygon_layer/polygon_layer.dart b/lib/src/layer/polygon_layer/polygon_layer.dart
index 6cf7172b5..dfddb6d31 100644
--- a/lib/src/layer/polygon_layer/polygon_layer.dart
+++ b/lib/src/layer/polygon_layer/polygon_layer.dart
@@ -15,6 +15,7 @@ import 'package:flutter_map/src/misc/offsets.dart';
import 'package:flutter_map/src/misc/point_in_polygon.dart';
import 'package:flutter_map/src/misc/simplify.dart';
import 'package:latlong2/latlong.dart' hide Path;
+import 'package:logger/logger.dart';
import 'package:polylabel/polylabel.dart';
part 'label.dart';
@@ -66,6 +67,17 @@ base class PolygonLayer
/// Defaults to `false`.
final bool drawLabelsLast;
+ /// Color to apply to the map where not covered by a polygon
+ ///
+ /// > [!WARNING]
+ /// > On the web, inverted filling may not work as expected in some cases.
+ /// > It will not match the behaviour seen on native platforms. Avoid allowing
+ /// > polygons to intersect, and avoid using holes within polygons.
+ /// > This is due to multiple limitations/bugs within Flutter. See the
+ /// > [online documentation](docs.fleaflet.dev/layers/polygon-layer#inverted-filling)
+ /// > for more info.
+ final Color? invertedFill;
+
/// {@macro fm.lhn.layerHitNotifier.usage}
final LayerHitNotifier? hitNotifier;
@@ -78,6 +90,7 @@ base class PolygonLayer
this.polygonCulling = true,
this.polygonLabels = true,
this.drawLabelsLast = false,
+ this.invertedFill,
this.hitNotifier,
super.simplificationTolerance,
}) : super();
@@ -90,6 +103,25 @@ class _PolygonLayerState extends State>
with
ProjectionSimplificationManagement<_ProjectedPolygon, Polygon,
PolygonLayer> {
+ @override
+ void didUpdateWidget(covariant PolygonLayer oldWidget) {
+ super.didUpdateWidget(oldWidget);
+
+ if (kDebugMode &&
+ kIsWeb &&
+ oldWidget.invertedFill == null &&
+ widget.invertedFill != null) {
+ Logger(printer: PrettyPrinter(methodCount: 0)).w(
+ '\x1B[1m\x1B[3mflutter_map\x1B[0m\nOn the web, inverted filling may '
+ 'not work as expected in some cases. It will not match the behaviour\n'
+ 'seen on native platforms.\nAvoid allowing polygons to intersect, and '
+ 'avoid using holes within polygons.\nThis is due to multiple '
+ 'limitations/bugs within Flutter.\nSee '
+ 'https://docs.fleaflet.dev/layers/polyline-layer#culling for more info.',
+ );
+ }
+ }
+
@override
_ProjectedPolygon projectElement({
required Projection projection,
@@ -174,6 +206,7 @@ class _PolygonLayerState extends State>
camera: camera,
polygonLabels: widget.polygonLabels,
drawLabelsLast: widget.drawLabelsLast,
+ invertedFill: widget.invertedFill,
debugAltRenderer: widget.debugAltRenderer,
hitNotifier: widget.hitNotifier,
),
diff --git a/lib/src/layer/polyline_layer/polyline_layer.dart b/lib/src/layer/polyline_layer/polyline_layer.dart
index f46b981b4..75d7df43d 100644
--- a/lib/src/layer/polyline_layer/polyline_layer.dart
+++ b/lib/src/layer/polyline_layer/polyline_layer.dart
@@ -29,8 +29,9 @@ base class PolylineLayer
/// Acceptable extent outside of viewport before culling polyline segments
///
/// May need to be increased if the [Polyline.strokeWidth] +
- /// [Polyline.borderStrokeWidth] is large. See online documentation for more
- /// information.
+ /// [Polyline.borderStrokeWidth] is large. See the
+ /// [online documentation](https://docs.fleaflet.dev/layers/polyline-layer#culling)
+ /// for more info.
///
/// Defaults to 10. Set to `null` to disable culling.
final double? cullingMargin;
diff --git a/lib/src/layer/shared/layer_interactivity/layer_hit_notifier.dart b/lib/src/layer/shared/layer_interactivity/layer_hit_notifier.dart
index 076d118bc..50b2d1474 100644
--- a/lib/src/layer/shared/layer_interactivity/layer_hit_notifier.dart
+++ b/lib/src/layer/shared/layer_interactivity/layer_hit_notifier.dart
@@ -21,7 +21,7 @@ typedef LayerHitNotifier = ValueNotifier?>;
///
/// Hit testing still occurs even if this is `null`.
///
-/// See online documentation for more detailed usage instructions. See the
+/// See the online documentation for more detailed usage instructions. See the
/// example project for an example implementation.
/// {@endtemplate}
// ignore: unused_element, constant_identifier_names
diff --git a/lib/src/layer/tile_layer/tile_layer.dart b/lib/src/layer/tile_layer/tile_layer.dart
index 0bee21485..f980257ac 100644
--- a/lib/src/layer/tile_layer/tile_layer.dart
+++ b/lib/src/layer/tile_layer/tile_layer.dart
@@ -277,21 +277,11 @@ class TileLayer extends StatefulWidget {
tileProvider = tileProvider ?? NetworkTileProvider(),
tileUpdateTransformer =
tileUpdateTransformer ?? TileUpdateTransformers.ignoreTapEvents {
- // Debug Logging
- if (kDebugMode &&
- urlTemplate != null &&
- urlTemplate!.contains('{s}.tile.openstreetmap.org')) {
- Logger(printer: PrettyPrinter(methodCount: 0)).w(
- '\x1B[1m\x1B[3mflutter_map\x1B[0m\nAvoid using subdomains with OSM\'s tile '
- 'server. Support may be become slow or be removed in future.\nSee '
- 'https://github.com/openstreetmap/operations/issues/737 for more info.',
- );
- }
if (kDebugMode &&
retinaMode == null &&
urlTemplate != null &&
urlTemplate!.contains('{r}')) {
- Logger(printer: PrettyPrinter(methodCount: 0)).w(
+ Logger(printer: PrettyPrinter(methodCount: 0)).i(
'\x1B[1m\x1B[3mflutter_map\x1B[0m\nThe URL template includes a retina '
"mode placeholder ('{r}') to retrieve native high-resolution\ntiles, "
'which improve appearance especially on high-density displays.\n'
@@ -299,8 +289,7 @@ class TileLayer extends StatefulWidget {
'will never retrieve these tiles.\nConsider using '
'`RetinaMode.isHighDensity` to toggle this property automatically, '
'otherwise ensure\nit is set appropriately.\n'
- 'See https://docs.fleaflet.dev/layers/tile-layer#retina-mode for '
- 'more info.',
+ 'See https://docs.fleaflet.dev/layers/tile-layer for more info.',
);
}
if (kDebugMode && kIsWeb && tileProvider is NetworkTileProvider?) {