From dc14ab406f0c975bdbe61227c51073f0da1a86ae Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 11 Jul 2024 16:50:20 +0900 Subject: [PATCH 1/8] [google_maps_flutter] Update example --- .../example/lib/custom_marker_icon.dart | 56 ++++ .../google_maps_flutter/example/lib/main.dart | 2 + .../example/lib/map_map_id.dart | 108 +++++++ .../example/lib/map_ui.dart | 34 +- .../example/lib/marker_icons.dart | 306 ++++++++++++++++-- .../example/lib/place_marker.dart | 28 +- .../example/lib/place_polyline.dart | 4 +- .../example/lib/readme_sample.dart | 72 +++++ 8 files changed, 537 insertions(+), 73 deletions(-) create mode 100644 packages/google_maps_flutter/example/lib/custom_marker_icon.dart create mode 100644 packages/google_maps_flutter/example/lib/map_map_id.dart create mode 100644 packages/google_maps_flutter/example/lib/readme_sample.dart diff --git a/packages/google_maps_flutter/example/lib/custom_marker_icon.dart b/packages/google_maps_flutter/example/lib/custom_marker_icon.dart new file mode 100644 index 000000000..8940762f0 --- /dev/null +++ b/packages/google_maps_flutter/example/lib/custom_marker_icon.dart @@ -0,0 +1,56 @@ +// 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 'dart:typed_data'; +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; + +/// Returns a generated png image in [ByteData] format with the requested size. +Future createCustomMarkerIconImage({required Size size}) async { + final ui.PictureRecorder recorder = ui.PictureRecorder(); + final Canvas canvas = Canvas(recorder); + final _MarkerPainter painter = _MarkerPainter(); + + painter.paint(canvas, size); + + final ui.Image image = await recorder + .endRecording() + .toImage(size.width.floor(), size.height.floor()); + + final ByteData? bytes = + await image.toByteData(format: ui.ImageByteFormat.png); + return bytes!; +} + +class _MarkerPainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + final Rect rect = Offset.zero & size; + const RadialGradient gradient = RadialGradient( + colors: [Colors.yellow, Colors.red], + stops: [0.4, 1.0], + ); + + // Draw radial gradient + canvas.drawRect( + rect, + Paint()..shader = gradient.createShader(rect), + ); + + // Draw diagonal black line + canvas.drawLine( + Offset.zero, + Offset(size.width, size.height), + Paint() + ..color = Colors.black + ..strokeWidth = 1, + ); + } + + @override + bool shouldRepaint(_MarkerPainter oldDelegate) => false; + @override + bool shouldRebuildSemantics(_MarkerPainter oldDelegate) => false; +} diff --git a/packages/google_maps_flutter/example/lib/main.dart b/packages/google_maps_flutter/example/lib/main.dart index 3b1e6361b..a690f21b7 100644 --- a/packages/google_maps_flutter/example/lib/main.dart +++ b/packages/google_maps_flutter/example/lib/main.dart @@ -8,6 +8,7 @@ import 'animate_camera.dart'; import 'lite_mode.dart'; import 'map_click.dart'; import 'map_coordinates.dart'; +import 'map_map_id.dart'; import 'map_ui.dart'; import 'marker_icons.dart'; import 'move_camera.dart'; @@ -37,6 +38,7 @@ final List _allPages = [ const SnapshotPage(), const LiteModePage(), const TileOverlayPage(), + const MapIdPage(), ]; /// MapsDemo is the Main Application. diff --git a/packages/google_maps_flutter/example/lib/map_map_id.dart b/packages/google_maps_flutter/example/lib/map_map_id.dart new file mode 100644 index 000000000..f15c8c793 --- /dev/null +++ b/packages/google_maps_flutter/example/lib/map_map_id.dart @@ -0,0 +1,108 @@ +// 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. + +// ignore_for_file: public_member_api_docs + +import 'package:flutter/material.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'page.dart'; + +class MapIdPage extends GoogleMapExampleAppPage { + const MapIdPage({Key? key}) + : super(const Icon(Icons.map), 'Cloud-based maps styling', key: key); + + @override + Widget build(BuildContext context) { + return const MapIdBody(); + } +} + +class MapIdBody extends StatefulWidget { + const MapIdBody({super.key}); + + @override + State createState() => MapIdBodyState(); +} + +const LatLng _kMapCenter = LatLng(52.4478, -3.5402); + +class MapIdBodyState extends State { + GoogleMapController? controller; + + Key _key = const Key('mapId#'); + String? _mapId; + final TextEditingController _mapIdController = TextEditingController(); + + @override + void initState() { + super.initState(); + } + + void _setMapId() { + setState(() { + _mapId = _mapIdController.text; + + // Change key to initialize new map instance for new mapId. + _key = Key(_mapId ?? 'mapId#'); + }); + } + + @override + Widget build(BuildContext context) { + final GoogleMap googleMap = GoogleMap( + onMapCreated: _onMapCreated, + initialCameraPosition: const CameraPosition( + target: _kMapCenter, + zoom: 7.0, + ), + key: _key, + cloudMapId: _mapId); + + final List columnChildren = [ + Padding( + padding: const EdgeInsets.all(10.0), + child: Center( + child: SizedBox( + width: 300.0, + height: 200.0, + child: googleMap, + ), + ), + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: TextField( + controller: _mapIdController, + decoration: const InputDecoration( + hintText: 'Map Id', + ), + )), + Padding( + padding: const EdgeInsets.all(10.0), + child: ElevatedButton( + onPressed: () => _setMapId(), + child: const Text( + 'Press to use specified map Id', + ), + )), + ]; + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: columnChildren, + ); + } + + @override + void dispose() { + _mapIdController.dispose(); + super.dispose(); + } + + void _onMapCreated(GoogleMapController controllerParam) { + setState(() { + controller = controllerParam; + }); + } +} diff --git a/packages/google_maps_flutter/example/lib/map_ui.dart b/packages/google_maps_flutter/example/lib/map_ui.dart index 5348c1001..26c0b2ab7 100644 --- a/packages/google_maps_flutter/example/lib/map_ui.dart +++ b/packages/google_maps_flutter/example/lib/map_ui.dart @@ -4,6 +4,7 @@ // ignore_for_file: public_member_api_docs +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show rootBundle; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -59,6 +60,7 @@ class MapUiBodyState extends State { bool _myLocationButtonEnabled = true; late GoogleMapController _controller; bool _nightMode = false; + String _mapStyle = ''; @override void initState() { @@ -243,27 +245,18 @@ class MapUiBodyState extends State { return rootBundle.loadString(path); } - void _setMapStyle(String mapStyle) { - setState(() { - _nightMode = true; - _controller.setMapStyle(mapStyle); - }); - } - // Should only be called if _isMapCreated is true. Widget _nightModeToggler() { assert(_isMapCreated); return TextButton( child: Text('${_nightMode ? 'disable' : 'enable'} night mode'), - onPressed: () { - if (_nightMode) { - setState(() { - _nightMode = false; - _controller.setMapStyle(null); - }); - } else { - _getFileData('assets/night_mode.json').then(_setMapStyle); - } + onPressed: () async { + _nightMode = !_nightMode; + final String style = + _nightMode ? await _getFileData('assets/night_mode.json') : ''; + setState(() { + _mapStyle = style; + }); }, ); } @@ -278,6 +271,7 @@ class MapUiBodyState extends State { cameraTargetBounds: _cameraTargetBounds, minMaxZoomPreference: _minMaxZoomPreference, mapType: _mapType, + style: _mapStyle, rotateGesturesEnabled: _rotateGesturesEnabled, scrollGesturesEnabled: _scrollGesturesEnabled, tiltGesturesEnabled: _tiltGesturesEnabled, @@ -352,5 +346,13 @@ class MapUiBodyState extends State { _controller = controller; _isMapCreated = true; }); + // Log any style errors to the console for debugging. + if (kDebugMode) { + _controller.getStyleError().then((String? error) { + if (error != null) { + debugPrint(error); + } + }); + } } } diff --git a/packages/google_maps_flutter/example/lib/marker_icons.dart b/packages/google_maps_flutter/example/lib/marker_icons.dart index 847e5ae36..166bba62d 100644 --- a/packages/google_maps_flutter/example/lib/marker_icons.dart +++ b/packages/google_maps_flutter/example/lib/marker_icons.dart @@ -5,9 +5,13 @@ // ignore_for_file: public_member_api_docs // ignore_for_file: unawaited_futures +import 'dart:async'; + +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'custom_marker_icon.dart'; import 'page.dart'; class MarkerIconsPage extends GoogleMapExampleAppPage { @@ -29,66 +33,302 @@ class MarkerIconsBody extends StatefulWidget { const LatLng _kMapCenter = LatLng(52.4478, -3.5402); +enum _MarkerSizeOption { + original, + width30, + height40, + size30x60, + size120x60, +} + class MarkerIconsBodyState extends State { + final Size _markerAssetImageSize = const Size(48, 48); + _MarkerSizeOption _currentSizeOption = _MarkerSizeOption.original; + Set _markers = {}; + bool _scalingEnabled = true; + bool _mipMapsEnabled = true; GoogleMapController? controller; - BitmapDescriptor? _markerIcon; + AssetMapBitmap? _markerIconAsset; + BytesMapBitmap? _markerIconBytes; + final int _markersAmountPerType = 15; + bool get _customSizeEnabled => + _currentSizeOption != _MarkerSizeOption.original; @override Widget build(BuildContext context) { - _createMarkerImageFromAsset(context); + _createCustomMarkerIconImages(context); + final Size referenceSize = _getMarkerReferenceSize(); return Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Center( - child: SizedBox( - width: 350.0, - height: 300.0, - child: GoogleMap( - initialCameraPosition: const CameraPosition( - target: _kMapCenter, - zoom: 7.0, + Column(children: [ + Center( + child: SizedBox( + width: 350.0, + height: 300.0, + child: GoogleMap( + initialCameraPosition: const CameraPosition( + target: _kMapCenter, + zoom: 7.0, + ), + markers: _markers, + onMapCreated: _onMapCreated, ), - markers: {_createMarker()}, - onMapCreated: _onMapCreated, ), ), - ) + TextButton( + onPressed: () => _toggleScaling(context), + child: Text(_scalingEnabled + ? 'Disable auto scaling' + : 'Enable auto scaling'), + ), + if (_scalingEnabled) ...[ + Container( + width: referenceSize.width, + height: referenceSize.height, + decoration: BoxDecoration( + border: Border.all(), + ), + ), + Text( + 'Reference box with size of ${referenceSize.width} x ${referenceSize.height} in logical pixels.'), + const SizedBox(height: 10), + Image.asset( + 'assets/red_square.png', + scale: _mipMapsEnabled ? null : 1.0, + ), + const Text('Asset image rendered with flutter'), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Marker size:'), + const SizedBox(width: 10), + DropdownButton<_MarkerSizeOption>( + value: _currentSizeOption, + onChanged: (_MarkerSizeOption? newValue) { + if (newValue != null) { + setState(() { + _currentSizeOption = newValue; + _updateMarkerImages(context); + }); + } + }, + items: + _MarkerSizeOption.values.map((_MarkerSizeOption option) { + return DropdownMenuItem<_MarkerSizeOption>( + value: option, + child: Text(_getMarkerSizeOptionName(option)), + ); + }).toList(), + ) + ], + ), + ], + TextButton( + onPressed: () => _toggleMipMaps(context), + child: Text(_mipMapsEnabled ? 'Disable mipmaps' : 'Enable mipmaps'), + ), + ]) ], ); } - Marker _createMarker() { - if (_markerIcon != null) { - return Marker( - markerId: const MarkerId('marker_1'), - position: _kMapCenter, - icon: _markerIcon!, - ); + String _getMarkerSizeOptionName(_MarkerSizeOption option) { + switch (option) { + case _MarkerSizeOption.original: + return 'Original'; + case _MarkerSizeOption.width30: + return 'Width 30'; + case _MarkerSizeOption.height40: + return 'Height 40'; + case _MarkerSizeOption.size30x60: + return '30x60'; + case _MarkerSizeOption.size120x60: + return '120x60'; + } + } + + (double? width, double? height) _getCurrentMarkerSize() { + if (_scalingEnabled) { + switch (_currentSizeOption) { + case _MarkerSizeOption.width30: + return (30, null); + case _MarkerSizeOption.height40: + return (null, 40); + case _MarkerSizeOption.size30x60: + return (30, 60); + case _MarkerSizeOption.size120x60: + return (120, 60); + case _MarkerSizeOption.original: + return (_markerAssetImageSize.width, _markerAssetImageSize.height); + } } else { - return const Marker( - markerId: MarkerId('marker_1'), - position: _kMapCenter, - ); + return (_markerAssetImageSize.width, _markerAssetImageSize.height); } } - Future _createMarkerImageFromAsset(BuildContext context) async { - if (_markerIcon == null) { - final ImageConfiguration imageConfiguration = - createLocalImageConfiguration(context, size: const Size.square(48)); - BitmapDescriptor.fromAssetImage( - imageConfiguration, 'assets/red_square.png') - .then(_updateBitmap); + // Helper method to calculate reference size for custom marker size. + Size _getMarkerReferenceSize() { + final (double? width, double? height) = _getCurrentMarkerSize(); + + // Calculates reference size using _markerAssetImageSize aspect ration: + + if (width != null && height != null) { + return Size(width, height); + } else if (width != null) { + return Size(width, + width * _markerAssetImageSize.height / _markerAssetImageSize.width); + } else if (height != null) { + return Size( + height * _markerAssetImageSize.width / _markerAssetImageSize.height, + height); + } else { + return _markerAssetImageSize; } } - void _updateBitmap(BitmapDescriptor bitmap) { + void _toggleMipMaps(BuildContext context) { + _mipMapsEnabled = !_mipMapsEnabled; + _updateMarkerImages(context); + } + + void _toggleScaling(BuildContext context) { + _scalingEnabled = !_scalingEnabled; + _updateMarkerImages(context); + } + + void _updateMarkerImages(BuildContext context) { + _updateMarkerAssetImage(context); + _updateMarkerBytesImage(context); + _updateMarkers(); + } + + Marker _createAssetMarker(int index) { + final LatLng position = + LatLng(_kMapCenter.latitude - (index * 0.5), _kMapCenter.longitude - 1); + return Marker( + markerId: MarkerId('marker_asset_$index'), + position: position, + icon: _markerIconAsset!, + ); + } + + Marker _createBytesMarker(int index) { + final LatLng position = + LatLng(_kMapCenter.latitude - (index * 0.5), _kMapCenter.longitude + 1); + + return Marker( + markerId: MarkerId('marker_bytes_$index'), + position: position, + icon: _markerIconBytes!, + ); + } + + void _updateMarkers() { + final Set markers = {}; + for (int i = 0; i < _markersAmountPerType; i++) { + if (_markerIconAsset != null) { + markers.add(_createAssetMarker(i)); + } + if (_markerIconBytes != null) { + markers.add(_createBytesMarker(i)); + } + } setState(() { - _markerIcon = bitmap; + _markers = markers; }); } + Future _updateMarkerAssetImage(BuildContext context) async { + // Width and height are used only for custom size. + final (double? width, double? height) = + _scalingEnabled && _customSizeEnabled + ? _getCurrentMarkerSize() + : (null, null); + + AssetMapBitmap assetMapBitmap; + if (_mipMapsEnabled) { + final ImageConfiguration imageConfiguration = + createLocalImageConfiguration( + context, + ); + + assetMapBitmap = await AssetMapBitmap.create( + imageConfiguration, + 'assets/red_square.png', + width: width, + height: height, + bitmapScaling: + _scalingEnabled ? MapBitmapScaling.auto : MapBitmapScaling.none, + ); + } else { + // Uses hardcoded asset path + // This bypasses the asset resolving logic and allows to load the asset + // with precise path. + assetMapBitmap = AssetMapBitmap( + 'assets/red_square.png', + width: width, + height: height, + bitmapScaling: + _scalingEnabled ? MapBitmapScaling.auto : MapBitmapScaling.none, + ); + } + + _updateAssetBitmap(assetMapBitmap); + } + + Future _updateMarkerBytesImage(BuildContext context) async { + final double? devicePixelRatio = + MediaQuery.maybeDevicePixelRatioOf(context); + + final Size bitmapLogicalSize = _getMarkerReferenceSize(); + final double? imagePixelRatio = _scalingEnabled ? devicePixelRatio : null; + + // Create canvasSize with physical marker size + final Size canvasSize = Size( + bitmapLogicalSize.width * (imagePixelRatio ?? 1.0), + bitmapLogicalSize.height * (imagePixelRatio ?? 1.0)); + + final ByteData bytes = await createCustomMarkerIconImage(size: canvasSize); + + // Width and height are used only for custom size. + final (double? width, double? height) = + _scalingEnabled && _customSizeEnabled + ? _getCurrentMarkerSize() + : (null, null); + + final BytesMapBitmap bitmap = BytesMapBitmap(bytes.buffer.asUint8List(), + imagePixelRatio: imagePixelRatio, + width: width, + height: height, + bitmapScaling: + _scalingEnabled ? MapBitmapScaling.auto : MapBitmapScaling.none); + + _updateBytesBitmap(bitmap); + } + + void _updateAssetBitmap(AssetMapBitmap bitmap) { + _markerIconAsset = bitmap; + _updateMarkers(); + } + + void _updateBytesBitmap(BytesMapBitmap bitmap) { + _markerIconBytes = bitmap; + _updateMarkers(); + } + + void _createCustomMarkerIconImages(BuildContext context) { + if (_markerIconAsset == null) { + _updateMarkerAssetImage(context); + } + + if (_markerIconBytes == null) { + _updateMarkerBytesImage(context); + } + } + void _onMapCreated(GoogleMapController controllerParam) { setState(() { controller = controllerParam; diff --git a/packages/google_maps_flutter/example/lib/place_marker.dart b/packages/google_maps_flutter/example/lib/place_marker.dart index dc3a08705..1534f3b64 100644 --- a/packages/google_maps_flutter/example/lib/place_marker.dart +++ b/packages/google_maps_flutter/example/lib/place_marker.dart @@ -7,11 +7,11 @@ import 'dart:async'; import 'dart:math'; import 'dart:typed_data'; -import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'custom_marker_icon.dart'; import 'page.dart'; class PlaceMarkerPage extends GoogleMapExampleAppPage { @@ -266,26 +266,10 @@ class PlaceMarkerBodyState extends State { }); } - Future _getAssetIcon(BuildContext context) async { - final Completer bitmapIcon = - Completer(); - final ImageConfiguration config = createLocalImageConfiguration(context); - - const AssetImage('assets/red_square.png') - .resolve(config) - .addListener(ImageStreamListener((ImageInfo image, bool sync) async { - final ByteData? bytes = - await image.image.toByteData(format: ImageByteFormat.png); - if (bytes == null) { - bitmapIcon.completeError(Exception('Unable to encode icon')); - return; - } - final BitmapDescriptor bitmap = - BitmapDescriptor.fromBytes(bytes.buffer.asUint8List()); - bitmapIcon.complete(bitmap); - })); - - return bitmapIcon.future; + Future _getMarkerIcon(BuildContext context) async { + const Size canvasSize = Size(48, 48); + final ByteData bytes = await createCustomMarkerIconImage(size: canvasSize); + return BytesMapBitmap(bytes.buffer.asUint8List()); } @override @@ -382,7 +366,7 @@ class PlaceMarkerBodyState extends State { onPressed: selectedId == null ? null : () { - _getAssetIcon(context).then( + _getMarkerIcon(context).then( (BitmapDescriptor icon) { _setMarkerIcon(selectedId, icon); }, diff --git a/packages/google_maps_flutter/example/lib/place_polyline.dart b/packages/google_maps_flutter/example/lib/place_polyline.dart index e7997fa44..7cb07ae37 100644 --- a/packages/google_maps_flutter/example/lib/place_polyline.dart +++ b/packages/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/example/lib/readme_sample.dart b/packages/google_maps_flutter/example/lib/readme_sample.dart new file mode 100644 index 000000000..672a37187 --- /dev/null +++ b/packages/google_maps_flutter/example/lib/readme_sample.dart @@ -0,0 +1,72 @@ +// 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. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; + +void main() => runApp(const MyApp()); + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + title: 'Flutter Google Maps Demo', + home: MapSample(), + ); + } +} + +// #docregion MapSample +class MapSample extends StatefulWidget { + const MapSample({super.key}); + + @override + State createState() => MapSampleState(); +} + +class MapSampleState extends State { + final Completer _controller = + Completer(); + + static const CameraPosition _kGooglePlex = CameraPosition( + target: LatLng(37.42796133580664, -122.085749655962), + zoom: 14.4746, + ); + + static const CameraPosition _kLake = CameraPosition( + bearing: 192.8334901395799, + target: LatLng(37.43296265331129, -122.08832357078792), + tilt: 59.440717697143555, + zoom: 19.151926040649414); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: GoogleMap( + mapType: MapType.hybrid, + initialCameraPosition: _kGooglePlex, + onMapCreated: (GoogleMapController controller) { + _controller.complete(controller); + }, + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: _goToTheLake, + label: const Text('To the lake!'), + icon: const Icon(Icons.directions_boat), + ), + ); + } + + Future _goToTheLake() async { + final GoogleMapController controller = await _controller.future; + await controller.animateCamera(CameraUpdate.newCameraPosition(_kLake)); + } +} +// #enddocregion MapSample From 84af76c300d88b010cf8709ff56ce5cd0a57b87c Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 11 Jul 2024 18:55:02 +0900 Subject: [PATCH 2/8] [google_maps_flutter] Support BitmapDescriptor.asset/bytes - Deprecates BitmapDescriptor.fromAssetImage in favor of BitmapDescriptor.asset and AssetMapBitmap.create. - Deprecates BitmapDescriptor.fromBytes in favor of BitmapDescriptor.bytes and BytesMapBitmap https://pub.dev/packages/google_maps_flutter_platform_interface/changelog#280 --- .../google_maps_flutter/lib/src/convert.dart | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/packages/google_maps_flutter/lib/src/convert.dart b/packages/google_maps_flutter/lib/src/convert.dart index ef2f0c553..da2bae5d3 100644 --- a/packages/google_maps_flutter/lib/src/convert.dart +++ b/packages/google_maps_flutter/lib/src/convert.dart @@ -251,23 +251,36 @@ util.GMarkerOptions _markerOptionsFromMarker( util.GIcon? icon; if (iconConfig.isNotEmpty) { - if (iconConfig[0] == 'fromAssetImage') { + if (iconConfig[0] == 'asset') { assert(iconConfig.length >= 2); - // iconConfig[2] contains the DPIs of the screen, but that information is - // already encoded in the iconConfig[1] - icon = util.GIcon()..url = '../${iconConfig[1]}'; - - // iconConfig[3] may contain the [width, height] of the image, if passed! - if (iconConfig.length >= 4 && iconConfig[3] != null) { - final List rawIconSize = iconConfig[3]! as List; - final util.GSize size = - util.GSize(rawIconSize[0] as num?, rawIconSize[1] as num?); - icon - ..size = size - ..scaledSize = size; + final Map assetConfig = + iconConfig[1]! as Map; + icon = util.GIcon()..url = '../${assetConfig['assetName']}'; + if (assetConfig['width'] != null || assetConfig['height'] != null) { + icon.size = util.GSize( + assetConfig['width'] != null + ? double.parse(assetConfig['width']!.toString()) + : null, + assetConfig['height'] != null + ? double.parse(assetConfig['height']!.toString()) + : null); + } + } else if (iconConfig[0] == 'bytes') { + assert(iconConfig.length >= 2); + final Map assetConfig = + iconConfig[1]! as Map; + icon = util.GIcon() + ..url = + 'data:image/png;base64,${base64Encode(assetConfig['byteData']! as List)}'; + if (assetConfig['width'] != null || assetConfig['height'] != null) { + icon.size = util.GSize( + assetConfig['width'] != null + ? double.parse(assetConfig['width']!.toString()) + : null, + assetConfig['height'] != null + ? double.parse(assetConfig['height']!.toString()) + : null); } - } else if (iconConfig[0] == 'fromBytes') { - throw UnimplementedError('Not Implemented'); } } From d6d7e1c1e627e014960a72b08c4863059d6ddf17 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Thu, 11 Jul 2024 19:15:03 +0900 Subject: [PATCH 3/8] Update pubspec, README and CHANGELOG --- packages/google_maps_flutter/CHANGELOG.md | 9 +++++++++ packages/google_maps_flutter/README.md | 10 ++++++++-- packages/google_maps_flutter/example/pubspec.yaml | 4 ++-- packages/google_maps_flutter/pubspec.yaml | 6 +++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/CHANGELOG.md index a1c829d5c..2854d6fc7 100644 --- a/packages/google_maps_flutter/CHANGELOG.md +++ b/packages/google_maps_flutter/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.1.7 + +* Update webview_flutter_lwe to 0.3.2. +* Update google_maps_flutter to 2.7.0. +* Update google_maps_flutter_platform_interface to 2.7.0. +* Update example code. +* Supports BitmapDescriptor.asset/bytes. +* Supports byte type marker icons. + ## 0.1.6 * Fix new lint warnings. diff --git a/packages/google_maps_flutter/README.md b/packages/google_maps_flutter/README.md index cbb2abde5..f23b83482 100644 --- a/packages/google_maps_flutter/README.md +++ b/packages/google_maps_flutter/README.md @@ -20,8 +20,8 @@ This package is not an _endorsed_ implementation of `google_maps_flutter`. There ```yaml dependencies: - google_maps_flutter: ^2.1.7 - google_maps_flutter_tizen: ^0.1.6 + google_maps_flutter: ^2.7.0 + google_maps_flutter_tizen: ^0.1.7 ``` For detailed usage, see https://pub.dev/packages/google_maps_flutter#sample-usage. @@ -31,3 +31,9 @@ In addition, you need a Maps JavaScript API Key to use this plugin. You can get ```js