From 793db5c4bcae9934bd18ae32f4ea9b1b8ff567f3 Mon Sep 17 00:00:00 2001 From: duzenko Date: Tue, 4 Jun 2019 17:41:41 +0300 Subject: [PATCH 1/8] Marker drag event --- .../googlemaps/GoogleMapController.java | 18 +++++++++++++++++- .../plugins/googlemaps/MarkersController.java | 16 ++++++++++++++++ .../example/lib/place_marker.dart | 3 +++ .../lib/src/controller.dart | 3 +++ .../lib/src/google_map.dart | 8 ++++++++ .../google_maps_flutter/lib/src/marker.dart | 5 +++++ 6 files changed, 52 insertions(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java index 31f532a1d18b..ef76c4ccafbe 100644 --- a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java +++ b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java @@ -59,7 +59,7 @@ final class GoogleMapController OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMapLongClickListener, - PlatformView { + PlatformView, GoogleMap.OnMarkerDragListener { private static final String TAG = "GoogleMapController"; private final int id; @@ -174,6 +174,7 @@ public void onMapReady(GoogleMap googleMap) { googleMap.setOnCameraMoveListener(this); googleMap.setOnCameraIdleListener(this); googleMap.setOnMarkerClickListener(this); + googleMap.setOnMarkerDragListener(this); googleMap.setOnPolygonClickListener(this); googleMap.setOnPolylineClickListener(this); googleMap.setOnCircleClickListener(this); @@ -369,6 +370,21 @@ public boolean onMarkerClick(Marker marker) { return markersController.onMarkerTap(marker.getId()); } + @Override + public void onMarkerDragStart(Marker marker) { + + } + + @Override + public void onMarkerDrag(Marker marker) { + + } + + @Override + public void onMarkerDragEnd(Marker marker) { + markersController.onMarkerDragEnd(marker.getId(), marker.getPosition()); + } + @Override public void onPolygonClick(Polygon polygon) { polygonsController.onPolygonTap(polygon.getId()); diff --git a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java index 6923a23fd586..441946c9ad84 100644 --- a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java +++ b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java @@ -5,6 +5,7 @@ package io.flutter.plugins.googlemaps; import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import io.flutter.plugin.common.MethodChannel; @@ -75,6 +76,21 @@ boolean onMarkerTap(String googleMarkerId) { return false; } + void onMarkerDragEnd(String googleMarkerId, LatLng latLng) { + String markerId = googleMapsMarkerIdToDartMarkerId.get(googleMarkerId); + if (markerId == null) { + return; + } + final Map data = new HashMap<>(); + data.put("markerId", markerId); + data.put("position", Convert.latLngToJson(latLng)); + methodChannel.invokeMethod("marker#onDragEnd", data); + MarkerController markerController = markerIdToController.get(markerId); + if (markerController != null) { +// return markerController.consumeTapEvents(); + } + } + void onInfoWindowTap(String googleMarkerId) { String markerId = googleMapsMarkerIdToDartMarkerId.get(googleMarkerId); if (markerId == null) { diff --git a/packages/google_maps_flutter/example/lib/place_marker.dart b/packages/google_maps_flutter/example/lib/place_marker.dart index c305984ce853..fefa52110f9e 100644 --- a/packages/google_maps_flutter/example/lib/place_marker.dart +++ b/packages/google_maps_flutter/example/lib/place_marker.dart @@ -89,6 +89,9 @@ class PlaceMarkerBodyState extends State { onTap: () { _onMarkerTapped(markerId); }, + onDragEnd: (LatLng position) { + print(position); + }, ); setState(() { diff --git a/packages/google_maps_flutter/lib/src/controller.dart b/packages/google_maps_flutter/lib/src/controller.dart index af86f89b5f9e..0dee0d922704 100644 --- a/packages/google_maps_flutter/lib/src/controller.dart +++ b/packages/google_maps_flutter/lib/src/controller.dart @@ -57,6 +57,9 @@ class GoogleMapController { case 'marker#onTap': _googleMapState.onMarkerTap(call.arguments['markerId']); break; + case 'marker#onDragEnd': + _googleMapState.onMarkerDragEnd(call.arguments['markerId'], LatLng._fromJson(call.arguments['position'])); + break; case 'infoWindow#onTap': _googleMapState.onInfoWindowTap(call.arguments['markerId']); break; diff --git a/packages/google_maps_flutter/lib/src/google_map.dart b/packages/google_maps_flutter/lib/src/google_map.dart index 775b94a329ba..7237ce011307 100644 --- a/packages/google_maps_flutter/lib/src/google_map.dart +++ b/packages/google_maps_flutter/lib/src/google_map.dart @@ -287,6 +287,14 @@ class _GoogleMapState extends State { } } + void onMarkerDragEnd(String markerIdParam, LatLng position) { + assert(markerIdParam != null); + final MarkerId markerId = MarkerId(markerIdParam); + if (_markers[markerId]?.onDragEnd != null) { + _markers[markerId].onDragEnd(position); + } + } + void onPolygonTap(String polygonIdParam) { assert(polygonIdParam != null); final PolygonId polygonId = PolygonId(polygonIdParam); diff --git a/packages/google_maps_flutter/lib/src/marker.dart b/packages/google_maps_flutter/lib/src/marker.dart index cd39f689422d..1f64f0ee19ff 100644 --- a/packages/google_maps_flutter/lib/src/marker.dart +++ b/packages/google_maps_flutter/lib/src/marker.dart @@ -160,6 +160,7 @@ class Marker { this.visible = true, this.zIndex = 0.0, this.onTap, + this.onDragEnd, }) : assert(alpha == null || (0.0 <= alpha && alpha <= 1.0)); /// Uniquely identifies a [Marker]. @@ -216,6 +217,8 @@ class Marker { /// Callbacks to receive tap events for markers placed on this map. final VoidCallback onTap; + final ValueChanged onDragEnd; + /// Creates a new [Marker] object whose values are the same as this instance, /// unless overwritten by the specified parameters. Marker copyWith({ @@ -231,6 +234,7 @@ class Marker { bool visibleParam, double zIndexParam, VoidCallback onTapParam, + ValueChanged onDragEndParam, }) { return Marker( markerId: markerId, @@ -246,6 +250,7 @@ class Marker { visible: visibleParam ?? visible, zIndex: zIndexParam ?? zIndex, onTap: onTapParam ?? onTap, + onDragEnd: onDragEndParam ?? onDragEnd, ); } From f2abc0df00b95807b35396e4434f95c9409d8ffc Mon Sep 17 00:00:00 2001 From: duzenko Date: Thu, 6 Jun 2019 12:08:29 +0300 Subject: [PATCH 2/8] Formatting --- .../plugins/googlemaps/GoogleMapController.java | 11 ++++------- .../flutter/plugins/googlemaps/MarkersController.java | 4 ---- packages/google_maps_flutter/lib/src/controller.dart | 3 ++- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java index ef76c4ccafbe..af061a8d16af 100644 --- a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java +++ b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java @@ -59,7 +59,8 @@ final class GoogleMapController OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMapLongClickListener, - PlatformView, GoogleMap.OnMarkerDragListener { + PlatformView, + GoogleMap.OnMarkerDragListener { private static final String TAG = "GoogleMapController"; private final int id; @@ -371,14 +372,10 @@ public boolean onMarkerClick(Marker marker) { } @Override - public void onMarkerDragStart(Marker marker) { - - } + public void onMarkerDragStart(Marker marker) {} @Override - public void onMarkerDrag(Marker marker) { - - } + public void onMarkerDrag(Marker marker) {} @Override public void onMarkerDragEnd(Marker marker) { diff --git a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java index 441946c9ad84..1f863467f977 100644 --- a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java +++ b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java @@ -85,10 +85,6 @@ void onMarkerDragEnd(String googleMarkerId, LatLng latLng) { data.put("markerId", markerId); data.put("position", Convert.latLngToJson(latLng)); methodChannel.invokeMethod("marker#onDragEnd", data); - MarkerController markerController = markerIdToController.get(markerId); - if (markerController != null) { -// return markerController.consumeTapEvents(); - } } void onInfoWindowTap(String googleMarkerId) { diff --git a/packages/google_maps_flutter/lib/src/controller.dart b/packages/google_maps_flutter/lib/src/controller.dart index 0dee0d922704..aa9fcc15540a 100644 --- a/packages/google_maps_flutter/lib/src/controller.dart +++ b/packages/google_maps_flutter/lib/src/controller.dart @@ -58,7 +58,8 @@ class GoogleMapController { _googleMapState.onMarkerTap(call.arguments['markerId']); break; case 'marker#onDragEnd': - _googleMapState.onMarkerDragEnd(call.arguments['markerId'], LatLng._fromJson(call.arguments['position'])); + _googleMapState.onMarkerDragEnd(call.arguments['markerId'], + LatLng._fromJson(call.arguments['position'])); break; case 'infoWindow#onTap': _googleMapState.onInfoWindowTap(call.arguments['markerId']); From 3243508b09761113e6e419248e605c5a82641bad Mon Sep 17 00:00:00 2001 From: Anton Duzenko Date: Fri, 7 Jun 2019 08:17:18 -0700 Subject: [PATCH 3/8] iOS part --- .../ios/Classes/GoogleMapController.m | 5 +++++ .../ios/Classes/GoogleMapMarkerController.h | 2 ++ .../ios/Classes/GoogleMapMarkerController.m | 12 ++++++++++++ 3 files changed, 19 insertions(+) diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapController.m b/packages/google_maps_flutter/ios/Classes/GoogleMapController.m index fa496387bc2c..f6f118b206ca 100644 --- a/packages/google_maps_flutter/ios/Classes/GoogleMapController.m +++ b/packages/google_maps_flutter/ios/Classes/GoogleMapController.m @@ -339,6 +339,11 @@ - (BOOL)mapView:(GMSMapView*)mapView didTapMarker:(GMSMarker*)marker { return [_markersController onMarkerTap:markerId]; } +- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker { + NSString* markerId = marker.userData[0]; + [_markersController onMarkerDragEnd:markerId coordinate:marker.position]; +} + - (void)mapView:(GMSMapView*)mapView didTapInfoWindowOfMarker:(GMSMarker*)marker { NSString* markerId = marker.userData[0]; [_markersController onInfoWindowTap:markerId]; diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h index 898eddeb0792..7e2a77e92445 100644 --- a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h +++ b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h @@ -40,5 +40,7 @@ - (void)changeMarkers:(NSArray*)markersToChange; - (void)removeMarkerIds:(NSArray*)markerIdsToRemove; - (BOOL)onMarkerTap:(NSString*)markerId; +- (void)onMarkerDragEnd:(NSString*)markerId + coordinate:(CLLocationCoordinate2D)coordinate; - (void)onInfoWindowTap:(NSString*)markerId; @end diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m index cb5ef461c38c..0c3a6efc7b53 100644 --- a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m +++ b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m @@ -284,6 +284,18 @@ - (BOOL)onMarkerTap:(NSString*)markerId { [_methodChannel invokeMethod:@"marker#onTap" arguments:@{@"markerId" : markerId}]; return controller.consumeTapEvents; } +- (void)onMarkerDragEnd:(NSString*)markerId + coordinate:(CLLocationCoordinate2D)coordinate +{ + if (!markerId) { + return; + } + FLTGoogleMapMarkerController* controller = _markerIdToController[markerId]; + if (!controller) { + return; + } + [_methodChannel invokeMethod:@"marker#onDragEnd" arguments:@{@"markerId" : markerId, @"position" : PositionToJson(coordinate)}]; +} - (void)onInfoWindowTap:(NSString*)markerId { if (markerId && _markerIdToController[markerId]) { [_methodChannel invokeMethod:@"infoWindow#onTap" arguments:@{@"markerId" : markerId}]; From a0fb00d4e1a83ac9328002aebe98fa3944939f43 Mon Sep 17 00:00:00 2001 From: Anton Duzenko Date: Mon, 10 Jun 2019 02:22:17 -0700 Subject: [PATCH 4/8] Formatting --- .../ios/Classes/GoogleMapController.m | 6 +++--- .../ios/Classes/GoogleMapMarkerController.h | 3 +-- .../ios/Classes/GoogleMapMarkerController.m | 21 +++++++++---------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapController.m b/packages/google_maps_flutter/ios/Classes/GoogleMapController.m index f6f118b206ca..ede1e619f3cb 100644 --- a/packages/google_maps_flutter/ios/Classes/GoogleMapController.m +++ b/packages/google_maps_flutter/ios/Classes/GoogleMapController.m @@ -339,9 +339,9 @@ - (BOOL)mapView:(GMSMapView*)mapView didTapMarker:(GMSMarker*)marker { return [_markersController onMarkerTap:markerId]; } -- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker { - NSString* markerId = marker.userData[0]; - [_markersController onMarkerDragEnd:markerId coordinate:marker.position]; +- (void)mapView:(GMSMapView*)mapView didEndDraggingMarker:(GMSMarker*)marker { + NSString* markerId = marker.userData[0]; + [_markersController onMarkerDragEnd:markerId coordinate:marker.position]; } - (void)mapView:(GMSMapView*)mapView didTapInfoWindowOfMarker:(GMSMarker*)marker { diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h index 7e2a77e92445..7b8bccd7b462 100644 --- a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h +++ b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h @@ -40,7 +40,6 @@ - (void)changeMarkers:(NSArray*)markersToChange; - (void)removeMarkerIds:(NSArray*)markerIdsToRemove; - (BOOL)onMarkerTap:(NSString*)markerId; -- (void)onMarkerDragEnd:(NSString*)markerId - coordinate:(CLLocationCoordinate2D)coordinate; +- (void)onMarkerDragEnd:(NSString*)markerId coordinate:(CLLocationCoordinate2D)coordinate; - (void)onInfoWindowTap:(NSString*)markerId; @end diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m index 0c3a6efc7b53..91b4e7bce2b7 100644 --- a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m +++ b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m @@ -284,17 +284,16 @@ - (BOOL)onMarkerTap:(NSString*)markerId { [_methodChannel invokeMethod:@"marker#onTap" arguments:@{@"markerId" : markerId}]; return controller.consumeTapEvents; } -- (void)onMarkerDragEnd:(NSString*)markerId - coordinate:(CLLocationCoordinate2D)coordinate -{ - if (!markerId) { - return; - } - FLTGoogleMapMarkerController* controller = _markerIdToController[markerId]; - if (!controller) { - return; - } - [_methodChannel invokeMethod:@"marker#onDragEnd" arguments:@{@"markerId" : markerId, @"position" : PositionToJson(coordinate)}]; +- (void)onMarkerDragEnd:(NSString*)markerId coordinate:(CLLocationCoordinate2D)coordinate { + if (!markerId) { + return; + } + FLTGoogleMapMarkerController* controller = _markerIdToController[markerId]; + if (!controller) { + return; + } + [_methodChannel invokeMethod:@"marker#onDragEnd" + arguments:@{@"markerId" : markerId, @"position" : PositionToJson(coordinate)}]; } - (void)onInfoWindowTap:(NSString*)markerId { if (markerId && _markerIdToController[markerId]) { From 9b91ee47c5687b42e6cc5447060b31dd3c987f20 Mon Sep 17 00:00:00 2001 From: duzenko Date: Tue, 11 Jun 2019 13:29:35 +0300 Subject: [PATCH 5/8] Use example --- .../example/lib/place_marker.dart | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/google_maps_flutter/example/lib/place_marker.dart b/packages/google_maps_flutter/example/lib/place_marker.dart index fefa52110f9e..9adc8a8cd99d 100644 --- a/packages/google_maps_flutter/example/lib/place_marker.dart +++ b/packages/google_maps_flutter/example/lib/place_marker.dart @@ -53,8 +53,7 @@ class PlaceMarkerBodyState extends State { if (tappedMarker != null) { setState(() { if (markers.containsKey(selectedMarker)) { - final Marker resetOld = markers[selectedMarker] - .copyWith(iconParam: BitmapDescriptor.defaultMarker); + final Marker resetOld = markers[selectedMarker].copyWith(iconParam: BitmapDescriptor.defaultMarker); markers[selectedMarker] = resetOld; } selectedMarker = markerId; @@ -68,6 +67,32 @@ class PlaceMarkerBodyState extends State { } } + void _onMarkerDragEnd(MarkerId markerId, LatLng newPosition) async { + final Marker tappedMarker = markers[markerId]; + if (tappedMarker != null) { + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + actions: [ + FlatButton( + child: const Text('OK'), + onPressed: () => Navigator.of(context).pop(), + ) + ], + content: Padding( + padding: const EdgeInsets.symmetric(vertical: 66), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('Old position: ${tappedMarker.position}'), + Text('New position: $newPosition'), + ], + ))); + }); + } + } + void _add() { final int markerCount = markers.length; @@ -90,7 +115,7 @@ class PlaceMarkerBodyState extends State { _onMarkerTapped(markerId); }, onDragEnd: (LatLng position) { - print(position); + _onMarkerDragEnd(markerId, position); }, ); From 6717132c09f799db2f259a0d11cc4934c97a9a13 Mon Sep 17 00:00:00 2001 From: Anton Duzenko Date: Tue, 11 Jun 2019 03:32:55 -0700 Subject: [PATCH 6/8] Formatting --- packages/google_maps_flutter/example/lib/place_marker.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/example/lib/place_marker.dart b/packages/google_maps_flutter/example/lib/place_marker.dart index 9adc8a8cd99d..e5cd9a28e951 100644 --- a/packages/google_maps_flutter/example/lib/place_marker.dart +++ b/packages/google_maps_flutter/example/lib/place_marker.dart @@ -53,7 +53,8 @@ class PlaceMarkerBodyState extends State { if (tappedMarker != null) { setState(() { if (markers.containsKey(selectedMarker)) { - final Marker resetOld = markers[selectedMarker].copyWith(iconParam: BitmapDescriptor.defaultMarker); + final Marker resetOld = markers[selectedMarker] + .copyWith(iconParam: BitmapDescriptor.defaultMarker); markers[selectedMarker] = resetOld; } selectedMarker = markerId; From 275df7fa60b719c71c666240dec3d3810de3e310 Mon Sep 17 00:00:00 2001 From: duzenko Date: Tue, 11 Jun 2019 13:38:45 +0300 Subject: [PATCH 7/8] Common style --- .../io/flutter/plugins/googlemaps/GoogleMapController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java index 952ff8e1787e..b09329edd58c 100644 --- a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java +++ b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java @@ -60,8 +60,8 @@ final class GoogleMapController OnMapReadyCallback, GoogleMap.OnMapClickListener, GoogleMap.OnMapLongClickListener, - PlatformView, - GoogleMap.OnMarkerDragListener { + GoogleMap.OnMarkerDragListener, + PlatformView { private static final String TAG = "GoogleMapController"; private final int id; From 8a3b5a5eb78d74fe7f45616829bcde5b904cba58 Mon Sep 17 00:00:00 2001 From: duzenko Date: Mon, 22 Jul 2019 19:28:20 +0300 Subject: [PATCH 8/8] Changelog & pubspec --- packages/google_maps_flutter/CHANGELOG.md | 4 ++++ packages/google_maps_flutter/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/CHANGELOG.md index ba8774ce450a..e4376b4e0122 100644 --- a/packages/google_maps_flutter/CHANGELOG.md +++ b/packages/google_maps_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.20+1 + +* Marker drag event + ## 0.5.20 * Add map toolbar support diff --git a/packages/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/pubspec.yaml index 4ca1734202af..7b595046e1a3 100644 --- a/packages/google_maps_flutter/pubspec.yaml +++ b/packages/google_maps_flutter/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter description: A Flutter plugin for integrating Google Maps in iOS and Android applications. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter -version: 0.5.20 +version: 0.5.20+1 dependencies: flutter: