diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md index 25d015dc385..b1960ba3504 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 2.9.1 +* Splits CameraUpdate into dervied classes for different update cases. * Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. ## 2.9.0 diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart index 01126afb869..d0ee5af1153 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart @@ -110,22 +110,53 @@ class CameraPosition { 'CameraPosition(bearing: $bearing, target: $target, tilt: $tilt, zoom: $zoom)'; } +/// Indicates which type of camera update this instance represents. +enum CameraUpdateType { + /// New position for camera + newCameraPosition, + + /// New coordinates for camera + newLatLng, + + /// New coordinates bounding box + newLatLngBounds, + + /// New coordinate with zoom level + newLatLngZoom, + + /// Move by a scroll delta + scrollBy, + + /// Zoom by a relative change + zoomBy, + + /// Zoom to an absolute level + zoomTo, + + /// Zoom in + zoomIn, + + /// Zoom out + zoomOut, +} + /// Defines a camera move, supporting absolute moves as well as moves relative /// the current position. -class CameraUpdate { - const CameraUpdate._(this._json); +abstract class CameraUpdate { + const CameraUpdate._(this.updateType); + + /// Indicates which type of camera update this instance represents. + final CameraUpdateType updateType; /// Returns a camera update that moves the camera to the specified position. static CameraUpdate newCameraPosition(CameraPosition cameraPosition) { - return CameraUpdate._( - ['newCameraPosition', cameraPosition.toMap()], - ); + return CameraUpdateNewCameraPosition(cameraPosition); } /// Returns a camera update that moves the camera target to the specified /// geographical location. static CameraUpdate newLatLng(LatLng latLng) { - return CameraUpdate._(['newLatLng', latLng.toJson()]); + return CameraUpdateNewLatLng(latLng); } /// Returns a camera update that transforms the camera so that the specified @@ -133,19 +164,13 @@ class CameraUpdate { /// possible zoom level. A non-zero [padding] insets the bounding box from the /// map view's edges. The camera's new tilt and bearing will both be 0.0. static CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) { - return CameraUpdate._([ - 'newLatLngBounds', - bounds.toJson(), - padding, - ]); + return CameraUpdateNewLatLngBounds(bounds, padding); } /// Returns a camera update that moves the camera target to the specified /// geographical location and zoom level. static CameraUpdate newLatLngZoom(LatLng latLng, double zoom) { - return CameraUpdate._( - ['newLatLngZoom', latLng.toJson(), zoom], - ); + return CameraUpdateNewLatLngZoom(latLng, zoom); } /// Returns a camera update that moves the camera target the specified screen @@ -155,24 +180,14 @@ class CameraUpdate { /// the camera's target to a geographical location that is 50 to the east and /// 75 to the south of the current location, measured in screen coordinates. static CameraUpdate scrollBy(double dx, double dy) { - return CameraUpdate._( - ['scrollBy', dx, dy], - ); + return CameraUpdateScrollBy(dx, dy); } /// Returns a camera update that modifies the camera zoom level by the /// specified amount. The optional [focus] is a screen point whose underlying /// geographical location should be invariant, if possible, by the movement. static CameraUpdate zoomBy(double amount, [Offset? focus]) { - if (focus == null) { - return CameraUpdate._(['zoomBy', amount]); - } else { - return CameraUpdate._([ - 'zoomBy', - amount, - [focus.dx, focus.dy], - ]); - } + return CameraUpdateZoomBy(amount, focus); } /// Returns a camera update that zooms the camera in, bringing the camera @@ -180,7 +195,7 @@ class CameraUpdate { /// /// Equivalent to the result of calling `zoomBy(1.0)`. static CameraUpdate zoomIn() { - return const CameraUpdate._(['zoomIn']); + return const CameraUpdateZoomIn(); } /// Returns a camera update that zooms the camera out, bringing the camera @@ -188,16 +203,131 @@ class CameraUpdate { /// /// Equivalent to the result of calling `zoomBy(-1.0)`. static CameraUpdate zoomOut() { - return const CameraUpdate._(['zoomOut']); + return const CameraUpdateZoomOut(); } /// Returns a camera update that sets the camera zoom level. static CameraUpdate zoomTo(double zoom) { - return CameraUpdate._(['zoomTo', zoom]); + return CameraUpdateZoomTo(zoom); } - final Object _json; - /// Converts this object to something serializable in JSON. - Object toJson() => _json; + Object toJson(); +} + +/// Defines a camera move to a new position. +class CameraUpdateNewCameraPosition extends CameraUpdate { + /// Creates a camera move. + const CameraUpdateNewCameraPosition(this.cameraPosition) + : super._(CameraUpdateType.newCameraPosition); + + /// The new camera position. + final CameraPosition cameraPosition; + @override + Object toJson() => ['newCameraPosition', cameraPosition.toMap()]; +} + +/// Defines a camera move to a latitude and longitude. +class CameraUpdateNewLatLng extends CameraUpdate { + /// Creates a camera move to latitude and longitude. + const CameraUpdateNewLatLng(this.latLng) + : super._(CameraUpdateType.newLatLng); + + /// New latitude and longitude of the camera.. + final LatLng latLng; + @override + Object toJson() => ['newLatLng', latLng.toJson()]; +} + +/// Defines a camera move to a new bounding latitude and longitude range. +class CameraUpdateNewLatLngBounds extends CameraUpdate { + /// Creates a camera move to a bounding range. + const CameraUpdateNewLatLngBounds(this.bounds, this.padding) + : super._(CameraUpdateType.newLatLngBounds); + + /// The northeast and southwest bounding coordinates. + final LatLngBounds bounds; + + /// The amount of padding by which the view is inset. + final double padding; + @override + Object toJson() => ['newLatLngZoom', bounds.toJson(), padding]; +} + +/// Defines a camera move to new coordinates with a zoom level. +class CameraUpdateNewLatLngZoom extends CameraUpdate { + /// Creates a camera move with coordinates and zoom level. + const CameraUpdateNewLatLngZoom(this.latLng, this.zoom) + : super._(CameraUpdateType.newLatLngZoom); + + /// New coordinates of the camera. + final LatLng latLng; + + /// New zoom level of the camera. + final double zoom; + @override + Object toJson() => ['newLatLngZoom', latLng.toJson(), zoom]; +} + +/// Defines a camera scroll by a certain delta. +class CameraUpdateScrollBy extends CameraUpdate { + /// Creates a camera scroll. + const CameraUpdateScrollBy(this.dx, this.dy) + : super._(CameraUpdateType.scrollBy); + + /// Scroll delta x. + final double dx; + + /// Scroll delta y. + final double dy; + @override + Object toJson() => ['scrollBy', dx, dy]; +} + +/// Defines a relative camera zoom. +class CameraUpdateZoomBy extends CameraUpdate { + /// Creates a relative camera zoom. + const CameraUpdateZoomBy(this.amount, [this.focus]) + : super._(CameraUpdateType.zoomBy); + + /// Change in camera zoom amount. + final double amount; + + /// Optional point around which the zoom is focused. + final Offset? focus; + @override + Object toJson() => (focus == null) + ? ['zoomBy', amount] + : [ + 'zoomBy', + amount, + [focus!.dx, focus!.dy] + ]; +} + +/// Defines a camera zoom in. +class CameraUpdateZoomIn extends CameraUpdate { + /// Zooms in the camera. + const CameraUpdateZoomIn() : super._(CameraUpdateType.zoomIn); + @override + Object toJson() => ['zoomIn']; +} + +/// Defines a camera zoom out. +class CameraUpdateZoomOut extends CameraUpdate { + /// Zooms out the camera. + const CameraUpdateZoomOut() : super._(CameraUpdateType.zoomOut); + @override + Object toJson() => ['zoomOut']; +} + +/// Defines a camera zoom to an absolute zoom. +class CameraUpdateZoomTo extends CameraUpdate { + /// Creates a zoom to an absolute zoom level. + const CameraUpdateZoomTo(this.zoom) : super._(CameraUpdateType.zoomTo); + + /// New zoom level of the camera. + final double zoom; + @override + Object toJson() => ['zoomTo', zoom]; } diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml index 70705df49d0..805164c520d 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/google_maps_f issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.9.0 +version: 2.9.1 environment: sdk: ^3.3.0 diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/camera_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/camera_test.dart index 70e57aa67ac..43ee478127b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/camera_test.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/types/camera_test.dart @@ -20,4 +20,82 @@ void main() { expect(cameraPosition, cameraPositionFromJson); }); + + test('CameraUpdate.newCameraPosition', () { + const CameraPosition cameraPosition = CameraPosition( + target: LatLng(10.0, 15.0), bearing: 0.5, tilt: 30.0, zoom: 1.5); + final CameraUpdate cameraUpdate = + CameraUpdate.newCameraPosition(cameraPosition); + expect(cameraUpdate.runtimeType, CameraUpdateNewCameraPosition); + expect(cameraUpdate.updateType, CameraUpdateType.newCameraPosition); + cameraUpdate as CameraUpdateNewCameraPosition; + expect(cameraUpdate.cameraPosition, cameraPosition); + }); + + test('CameraUpdate.newLatLng', () { + const LatLng latLng = LatLng(1.0, 2.0); + final CameraUpdate cameraUpdate = CameraUpdate.newLatLng(latLng); + expect(cameraUpdate.runtimeType, CameraUpdateNewLatLng); + expect(cameraUpdate.updateType, CameraUpdateType.newLatLng); + cameraUpdate as CameraUpdateNewLatLng; + expect(cameraUpdate.latLng, latLng); + }); + + test('CameraUpdate.newLatLngBounds', () { + final LatLngBounds latLngBounds = LatLngBounds( + northeast: const LatLng(1.0, 2.0), southwest: const LatLng(-2.0, -3.0)); + const double padding = 1.0; + final CameraUpdate cameraUpdate = + CameraUpdate.newLatLngBounds(latLngBounds, padding); + expect(cameraUpdate.runtimeType, CameraUpdateNewLatLngBounds); + expect(cameraUpdate.updateType, CameraUpdateType.newLatLngBounds); + cameraUpdate as CameraUpdateNewLatLngBounds; + expect(cameraUpdate.bounds, latLngBounds); + expect(cameraUpdate.padding, padding); + }); + + test('CameraUpdate.newLatLngZoom', () { + const LatLng latLng = LatLng(1.0, 2.0); + const double zoom = 2.0; + final CameraUpdate cameraUpdate = CameraUpdate.newLatLngZoom(latLng, zoom); + expect(cameraUpdate.runtimeType, CameraUpdateNewLatLngZoom); + expect(cameraUpdate.updateType, CameraUpdateType.newLatLngZoom); + cameraUpdate as CameraUpdateNewLatLngZoom; + expect(cameraUpdate.latLng, latLng); + expect(cameraUpdate.zoom, zoom); + }); + + test('CameraUpdate.scrollBy', () { + const double dx = 2.0; + const double dy = 5.0; + final CameraUpdate cameraUpdate = CameraUpdate.scrollBy(dx, dy); + expect(cameraUpdate.runtimeType, CameraUpdateScrollBy); + expect(cameraUpdate.updateType, CameraUpdateType.scrollBy); + cameraUpdate as CameraUpdateScrollBy; + expect(cameraUpdate.dx, dx); + expect(cameraUpdate.dy, dy); + }); + + test('CameraUpdate.zoomBy', () { + const double amount = 1.5; + const Offset focus = Offset(-1.0, -2.0); + final CameraUpdate cameraUpdate = CameraUpdate.zoomBy(amount, focus); + expect(cameraUpdate.runtimeType, CameraUpdateZoomBy); + expect(cameraUpdate.updateType, CameraUpdateType.zoomBy); + cameraUpdate as CameraUpdateZoomBy; + expect(cameraUpdate.amount, amount); + expect(cameraUpdate.focus, focus); + }); + + test('CameraUpdate.zoomIn', () { + final CameraUpdate cameraUpdate = CameraUpdate.zoomIn(); + expect(cameraUpdate.runtimeType, CameraUpdateZoomIn); + expect(cameraUpdate.updateType, CameraUpdateType.zoomIn); + }); + + test('CameraUpdate.zoomOut', () { + final CameraUpdate cameraUpdate = CameraUpdate.zoomOut(); + expect(cameraUpdate.runtimeType, CameraUpdateZoomOut); + expect(cameraUpdate.updateType, CameraUpdateType.zoomOut); + }); }