From a61103b76a49246bb2b11b30a248b5bde0b35d93 Mon Sep 17 00:00:00 2001 From: Hari07 <22373191+Hari-07@users.noreply.github.com> Date: Wed, 29 May 2024 00:41:07 +0530 Subject: [PATCH] [google_maps_flutter] Implement polyline patterns in google maps ios (#5757) This PR Implements patterns in google maps ios polylines. Currently the patterns param is simply ignored on ios, despite the official google maps SDK for ios having instructions on how to achieve repeated patterns: https://developers.google.com/maps/documentation/ios-sdk/shapes#add-a-repeating-color-pattern-to-a-polyline *List which issues are fixed by this PR. You must list at least one issue.* https://github.com/flutter/flutter/issues/60083 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* Nil --- .../example/lib/place_polyline.dart | 4 +- .../example/lib/place_polyline.dart | 4 +- .../google_maps_flutter_ios/CHANGELOG.md | 4 + .../ios/Runner.xcodeproj/project.pbxproj | 6 +- ...TGoogleMapJSONConversionsConversionTests.m | 14 ++++ .../GoogleMapsPolylinesControllerTests.m | 81 +++++++++++++++++++ .../maps_example_dart/lib/place_polyline.dart | 4 +- .../ios/Classes/FLTGoogleMapJSONConversions.h | 15 ++++ .../ios/Classes/FLTGoogleMapJSONConversions.m | 22 +++++ .../ios/Classes/GoogleMapPolylineController.h | 6 ++ .../ios/Classes/GoogleMapPolylineController.m | 50 ++++++++---- .../GoogleMapPolylineController_Test.h | 24 ++++++ .../google_maps_flutter_ios-umbrella.h | 1 + .../google_maps_flutter_ios/pubspec.yaml | 2 +- 14 files changed, 213 insertions(+), 24 deletions(-) create mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/GoogleMapsPolylinesControllerTests.m create mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter/example/lib/place_polyline.dart b/packages/google_maps_flutter/google_maps_flutter/example/lib/place_polyline.dart index e7997fa44451a..7cb07ae37db9a 100644 --- a/packages/google_maps_flutter/google_maps_flutter/example/lib/place_polyline.dart +++ b/packages/google_maps_flutter/google_maps_flutter/example/lib/place_polyline.dart @@ -291,10 +291,10 @@ class PlacePolylineBodyState extends State { child: const Text('change joint type [Android only]'), ), TextButton( - onPressed: isIOS || (selectedId == null) + onPressed: (selectedId == null) ? null : () => _changePattern(selectedId), - child: const Text('change pattern [Android only]'), + child: const Text('change pattern'), ), ], ) diff --git a/packages/google_maps_flutter/google_maps_flutter_android/example/lib/place_polyline.dart b/packages/google_maps_flutter/google_maps_flutter_android/example/lib/place_polyline.dart index 659ef87e87f84..d008b7d3b97de 100644 --- a/packages/google_maps_flutter/google_maps_flutter_android/example/lib/place_polyline.dart +++ b/packages/google_maps_flutter/google_maps_flutter_android/example/lib/place_polyline.dart @@ -292,10 +292,10 @@ class PlacePolylineBodyState extends State { child: const Text('change joint type [Android only]'), ), TextButton( - onPressed: isIOS || (selectedId == null) + onPressed: (selectedId == null) ? null : () => _changePattern(selectedId), - child: const Text('change pattern [Android only]'), + child: const Text('change pattern'), ), ], ) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md index cf9231d6a0a37..3a0195b6ca0b9 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.6.1 + +* Adds support for patterns in polylines. + ## 2.6.0 * Updates the minimum allowed verison of the Google Maps SDK to 8.4, for privacy diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/Runner.xcodeproj/project.pbxproj b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/Runner.xcodeproj/project.pbxproj index d5b6d8248e087..660b466a2fdf7 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/Runner.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 4510D964F3B1259FEDD3ABA6 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7755F8F4BABC3D6A0BD4048B /* libPods-Runner.a */; }; + 478116522BEF8F47002F593E /* GoogleMapsPolylinesControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 478116512BEF8F47002F593E /* GoogleMapsPolylinesControllerTests.m */; }; 6851F3562835BC180032B7C8 /* FLTGoogleMapJSONConversionsConversionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6851F3552835BC180032B7C8 /* FLTGoogleMapJSONConversionsConversionTests.m */; }; 68E4726A2836FF0C00BDDDAC /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68E472692836FF0C00BDDDAC /* MapKit.framework */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; @@ -18,8 +19,8 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - F269303B2BB389BF00BF17C4 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = F269303A2BB389BF00BF17C4 /* assets */; }; 982F2A6C27BADE17003C81F4 /* PartiallyMockedMapView.m in Sources */ = {isa = PBXBuildFile; fileRef = 982F2A6B27BADE17003C81F4 /* PartiallyMockedMapView.m */; }; + F269303B2BB389BF00BF17C4 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = F269303A2BB389BF00BF17C4 /* assets */; }; F7151F13265D7ED70028CB91 /* GoogleMapsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F7151F12265D7ED70028CB91 /* GoogleMapsTests.m */; }; F7151F21265D7EE50028CB91 /* GoogleMapsUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = F7151F20265D7EE50028CB91 /* GoogleMapsUITests.m */; }; FC8F35FC8CD533B128950487 /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F267F68029D1A4E2E4C572A7 /* libPods-RunnerTests.a */; }; @@ -60,6 +61,7 @@ 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 = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 478116512BEF8F47002F593E /* GoogleMapsPolylinesControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoogleMapsPolylinesControllerTests.m; sourceTree = ""; }; 6851F3552835BC180032B7C8 /* FLTGoogleMapJSONConversionsConversionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTGoogleMapJSONConversionsConversionTests.m; sourceTree = ""; }; 68E472692836FF0C00BDDDAC /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/System/iOSSupport/System/Library/Frameworks/MapKit.framework; sourceTree = DEVELOPER_DIR; }; 733AFAB37683A9DA7512F09C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; @@ -203,6 +205,7 @@ F269303A2BB389BF00BF17C4 /* assets */, 6851F3552835BC180032B7C8 /* FLTGoogleMapJSONConversionsConversionTests.m */, F7151F12265D7ED70028CB91 /* GoogleMapsTests.m */, + 478116512BEF8F47002F593E /* GoogleMapsPolylinesControllerTests.m */, 982F2A6A27BADE17003C81F4 /* PartiallyMockedMapView.h */, 982F2A6B27BADE17003C81F4 /* PartiallyMockedMapView.m */, F7151F14265D7ED70028CB91 /* Info.plist */, @@ -467,6 +470,7 @@ F7151F13265D7ED70028CB91 /* GoogleMapsTests.m in Sources */, 6851F3562835BC180032B7C8 /* FLTGoogleMapJSONConversionsConversionTests.m in Sources */, 982F2A6C27BADE17003C81F4 /* PartiallyMockedMapView.m in Sources */, + 478116522BEF8F47002F593E /* GoogleMapsPolylinesControllerTests.m in Sources */, 0DD7B6C32B744EEF00E857FD /* FLTTileProviderControllerTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m index 0d7d3ee9b2b71..cc654606d8c0f 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/FLTGoogleMapJSONConversionsConversionTests.m @@ -288,4 +288,18 @@ - (void)testCameraUpdateFromChannelValueZoomTo { [classMockCameraUpdate stopMocking]; } +- (void)testLengthsFromPatterns { + NSArray *> *patterns = @[ @[ @"gap", @10 ], @[ @"dash", @6.4 ] ]; + + NSArray *spanLengths = [FLTGoogleMapJSONConversions spanLengthsFromPatterns:patterns]; + + XCTAssertEqual([spanLengths count], 2); + + NSNumber *firstSpanLength = spanLengths[0]; + NSNumber *secondSpanLength = spanLengths[1]; + + XCTAssertEqual(firstSpanLength.doubleValue, 10); + XCTAssertEqual(secondSpanLength.doubleValue, 6.4); +} + @end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/GoogleMapsPolylinesControllerTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/GoogleMapsPolylinesControllerTests.m new file mode 100644 index 0000000000000..84714f17c7f60 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios14/ios/RunnerTests/GoogleMapsPolylinesControllerTests.m @@ -0,0 +1,81 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@import google_maps_flutter_ios; +@import google_maps_flutter_ios.Test; +@import XCTest; +@import GoogleMaps; + +#import +#import +#import "PartiallyMockedMapView.h" + +@interface GoogleMapsPolylinesControllerTests : XCTestCase +@end + +@implementation GoogleMapsPolylinesControllerTests + +/// Returns GoogleMapPolylineController object instantiated with a mocked map instance +/// +/// @return An object of FLTGoogleMapPolylineController +- (FLTGoogleMapPolylineController *)polylineControllerWithMockedMap { + NSDictionary *polyline = @{ + @"points" : @[ + @[ @(52.4816), @(-3.1791) ], @[ @(54.043), @(-2.9925) ], @[ @(54.1396), @(-4.2739) ], + @[ @(53.4153), @(-4.0829) ] + ], + @"polylineId" : @"polyline_id_0", + }; + + CGRect frame = CGRectMake(0, 0, 100, 100); + GMSCameraPosition *camera = [[GMSCameraPosition alloc] initWithLatitude:0 longitude:0 zoom:0]; + + GMSMapViewOptions *mapViewOptions = [[GMSMapViewOptions alloc] init]; + mapViewOptions.frame = frame; + mapViewOptions.camera = camera; + + PartiallyMockedMapView *mapView = [[PartiallyMockedMapView alloc] initWithOptions:mapViewOptions]; + + GMSMutablePath *path = [FLTPolylinesController pathForPolyline:polyline]; + NSString *identifier = polyline[@"polylineId"]; + + FLTGoogleMapPolylineController *polylineControllerWithMockedMap = + [[FLTGoogleMapPolylineController alloc] initPolylineWithPath:path + identifier:identifier + mapView:mapView]; + + return polylineControllerWithMockedMap; +} + +- (void)testSetPatterns { + NSArray *styles = @[ + [GMSStrokeStyle solidColor:[UIColor clearColor]], [GMSStrokeStyle solidColor:[UIColor redColor]] + ]; + + NSArray *lengths = @[ @10, @10 ]; + + FLTGoogleMapPolylineController *polylineController = [self polylineControllerWithMockedMap]; + + XCTAssertNil(polylineController.polyline.spans); + + [polylineController setPattern:styles lengths:lengths]; + + // `GMSStyleSpan` doesn't implement `isEqual` so cannot be compared by value at present. + XCTAssertNotNil(polylineController.polyline.spans); +} + +- (void)testStrokeStylesFromPatterns { + NSArray *> *patterns = @[ @[ @"gap", @10 ], @[ @"dash", @10 ] ]; + UIColor *strokeColor = [UIColor redColor]; + + NSArray *patternStrokeStyle = + [FLTGoogleMapJSONConversions strokeStylesFromPatterns:patterns strokeColor:strokeColor]; + + XCTAssertEqual([patternStrokeStyle count], 2); + + // None of the parameters of `patternStrokeStyle` is observable, so we limit to testing + // the length of this output array. +} + +@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/place_polyline.dart b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/place_polyline.dart index 659ef87e87f84..d008b7d3b97de 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/place_polyline.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/shared/maps_example_dart/lib/place_polyline.dart @@ -292,10 +292,10 @@ class PlacePolylineBodyState extends State { child: const Text('change joint type [Android only]'), ), TextButton( - onPressed: isIOS || (selectedId == null) + onPressed: (selectedId == null) ? null : () => _changePattern(selectedId), - child: const Text('change pattern [Android only]'), + child: const Text('change pattern'), ), ], ) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h index cfccb7b0b5f99..1fc8d003d9146 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.h @@ -25,6 +25,21 @@ NS_ASSUME_NONNULL_BEGIN + (GMSMapViewType)mapViewTypeFromTypeValue:(NSNumber *)value; + (nullable GMSCameraUpdate *)cameraUpdateFromChannelValue:(NSArray *)channelValue; +/// Return GMS strokestyle object array populated using the patterns and stroke colors passed in. +/// +/// @param patterns An array of patterns for each stroke in the polyline. +/// @param strokeColor An array of color for each stroke in the polyline. +/// @return An array of GMSStrokeStyle. ++ (NSArray *)strokeStylesFromPatterns:(NSArray *> *)patterns + strokeColor:(UIColor *)strokeColor; + +/// Return GMS strokestyle object array populated using the patterns and stroke colors passed in. +/// Extracts the lengths of each stroke in the polyline from patterns input +/// +/// @param patterns An array of object representing the pattern params in the polyline. +/// @return Array of lengths. ++ (NSArray *)spanLengthsFromPatterns:(NSArray *> *)patterns; + @end NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m index d554c501b1e24..28307182f2c9b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/FLTGoogleMapJSONConversions.m @@ -141,4 +141,26 @@ + (nullable GMSCameraUpdate *)cameraUpdateFromChannelValue:(NSArray *)channelVal } return nil; } + ++ (NSArray *)strokeStylesFromPatterns:(NSArray *> *)patterns + strokeColor:(UIColor *)strokeColor { + NSMutableArray *strokeStyles = [[NSMutableArray alloc] initWithCapacity:[patterns count]]; + for (NSArray *pattern in patterns) { + NSString *patternType = pattern[0]; + UIColor *color = [patternType isEqualToString:@"gap"] ? [UIColor clearColor] : strokeColor; + [strokeStyles addObject:[GMSStrokeStyle solidColor:color]]; + } + + return strokeStyles; +} + ++ (NSArray *)spanLengthsFromPatterns:(NSArray *> *)patterns { + NSMutableArray *lengths = [[NSMutableArray alloc] initWithCapacity:[patterns count]]; + for (NSArray *pattern in patterns) { + NSNumber *length = [pattern count] > 1 ? pattern[1] : @0; + [lengths addObject:length]; + } + + return lengths; +} @end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.h index f85d1a3896fac..63061392e5ad4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.h @@ -11,6 +11,12 @@ identifier:(NSString *)identifier mapView:(GMSMapView *)mapView; - (void)removePolyline; + +/// Sets the pattern on polyline controller +/// +/// @param styles The styles for repeating pattern sections. +/// @param lengths The lengths for repeating pattern sections. +- (void)setPattern:(NSArray *)styles lengths:(NSArray *)lengths; @end @interface FLTPolylinesController : NSObject diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.m index 77601d4a1bb5c..47334576b1c74 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController.m @@ -12,6 +12,12 @@ @interface FLTGoogleMapPolylineController () @end +/// Returns dict[key], or nil if dict[key] is NSNull. +static id GetValueOrNilFromDict(NSDictionary *dict, NSString *key) { + id value = dict[key]; + return value == [NSNull null] ? nil : value; +} + @implementation FLTGoogleMapPolylineController - (instancetype)initPolylineWithPath:(GMSMutablePath *)path @@ -59,42 +65,54 @@ - (void)setGeodesic:(BOOL)isGeodesic { self.polyline.geodesic = isGeodesic; } +- (void)setPattern:(NSArray *)styles lengths:(NSArray *)lengths { + self.polyline.spans = GMSStyleSpans(self.polyline.path, styles, lengths, kGMSLengthRhumb); +} + - (void)interpretPolylineOptions:(NSDictionary *)data registrar:(NSObject *)registrar { - NSNumber *consumeTapEvents = data[@"consumeTapEvents"]; - if (consumeTapEvents && consumeTapEvents != (id)[NSNull null]) { + NSNumber *consumeTapEvents = GetValueOrNilFromDict(data, @"consumeTapEvents"); + if (consumeTapEvents) { [self setConsumeTapEvents:[consumeTapEvents boolValue]]; } - NSNumber *visible = data[@"visible"]; - if (visible && visible != (id)[NSNull null]) { + NSNumber *visible = GetValueOrNilFromDict(data, @"visible"); + if (visible) { [self setVisible:[visible boolValue]]; } - NSNumber *zIndex = data[@"zIndex"]; - if (zIndex && zIndex != (id)[NSNull null]) { + NSNumber *zIndex = GetValueOrNilFromDict(data, @"zIndex"); + if (zIndex) { [self setZIndex:[zIndex intValue]]; } - NSArray *points = data[@"points"]; - if (points && points != (id)[NSNull null]) { + NSArray *points = GetValueOrNilFromDict(data, @"points"); + if (points) { [self setPoints:[FLTGoogleMapJSONConversions pointsFromLatLongs:points]]; } - NSNumber *strokeColor = data[@"color"]; - if (strokeColor && strokeColor != (id)[NSNull null]) { + NSNumber *strokeColor = GetValueOrNilFromDict(data, @"color"); + if (strokeColor) { [self setColor:[FLTGoogleMapJSONConversions colorFromRGBA:strokeColor]]; } - NSNumber *strokeWidth = data[@"width"]; - if (strokeWidth && strokeWidth != (id)[NSNull null]) { + NSNumber *strokeWidth = GetValueOrNilFromDict(data, @"width"); + if (strokeWidth) { [self setStrokeWidth:[strokeWidth intValue]]; } - NSNumber *geodesic = data[@"geodesic"]; - if (geodesic && geodesic != (id)[NSNull null]) { + NSNumber *geodesic = GetValueOrNilFromDict(data, @"geodesic"); + if (geodesic) { [self setGeodesic:geodesic.boolValue]; } + + NSArray *patterns = GetValueOrNilFromDict(data, @"pattern"); + if (patterns) { + [self + setPattern:[FLTGoogleMapJSONConversions strokeStylesFromPatterns:patterns + strokeColor:self.polyline.strokeColor] + lengths:[FLTGoogleMapJSONConversions spanLengthsFromPatterns:patterns]]; + } } @end @@ -125,7 +143,7 @@ - (instancetype)init:(FlutterMethodChannel *)methodChannel } - (void)addPolylines:(NSArray *)polylinesToAdd { for (NSDictionary *polyline in polylinesToAdd) { - GMSMutablePath *path = [FLTPolylinesController getPath:polyline]; + GMSMutablePath *path = [FLTPolylinesController pathForPolyline:polyline]; NSString *identifier = polyline[@"polylineId"]; FLTGoogleMapPolylineController *controller = [[FLTGoogleMapPolylineController alloc] initPolylineWithPath:path @@ -171,7 +189,7 @@ - (bool)hasPolylineWithIdentifier:(NSString *)identifier { } return self.polylineIdentifierToController[identifier] != nil; } -+ (GMSMutablePath *)getPath:(NSDictionary *)polyline { ++ (GMSMutablePath *)pathForPolyline:(NSDictionary *)polyline { NSArray *pointArray = polyline[@"points"]; NSArray *points = [FLTGoogleMapJSONConversions pointsFromLatLongs:pointArray]; GMSMutablePath *path = [GMSMutablePath path]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController_Test.h new file mode 100644 index 0000000000000..2b6e91e5d123b --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/GoogleMapPolylineController_Test.h @@ -0,0 +1,24 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "GoogleMapPolylineController.h" + +/// Internal APIs exposed for unit testing +@interface FLTGoogleMapPolylineController (Test) + +/// Polyline instance the controller is attached to +@property(strong, nonatomic) GMSPolyline *polyline; + +@end + +/// Internal APIs explosed for unit testing +@interface FLTPolylinesController (Test) + +/// Returns the path for polyline based on the points(locations) the polyline has. +/// +/// @param polyline The polyline instance for which path is calculated. +/// @return An instance of GMSMutablePath. ++ (GMSMutablePath *)pathForPolyline:(NSDictionary *)polyline; + +@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/google_maps_flutter_ios-umbrella.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/google_maps_flutter_ios-umbrella.h index 791c3aaea6c32..4f331de069b40 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/google_maps_flutter_ios-umbrella.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/Classes/google_maps_flutter_ios-umbrella.h @@ -6,6 +6,7 @@ #import #import #import +#import FOUNDATION_EXPORT double google_maps_flutterVersionNumber; FOUNDATION_EXPORT const unsigned char google_maps_flutterVersionString[]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml index e98f7209380dd..df74168cb1049 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter_ios description: iOS implementation of the google_maps_flutter plugin. repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 2.6.0 +version: 2.6.1 environment: sdk: ^3.2.3