5
5
// ignore_for_file: public_member_api_docs
6
6
// ignore_for_file: unawaited_futures
7
7
8
+ import 'dart:async' ;
9
+ import 'dart:math' ;
10
+ import 'dart:typed_data' ;
11
+
8
12
import 'package:flutter/material.dart' ;
9
13
import 'package:google_maps_flutter/google_maps_flutter.dart' ;
10
14
15
+ import 'custom_marker_icon.dart' ;
11
16
import 'page.dart' ;
12
17
13
18
class MarkerIconsPage extends GoogleMapExampleAppPage {
@@ -30,65 +35,235 @@ class MarkerIconsBody extends StatefulWidget {
30
35
const LatLng _kMapCenter = LatLng (52.4478 , - 3.5402 );
31
36
32
37
class MarkerIconsBodyState extends State <MarkerIconsBody > {
38
+ final double _markerAssetImageSize = 48 ;
39
+ final Size _customSize = const Size (55 , 30 );
40
+ Set <Marker > _markers = < Marker > {};
41
+ double _markerScale = 1.0 ;
42
+ bool _scalingEnabled = true ;
43
+ bool _customSizeEnabled = false ;
44
+ bool _mipMapsEnabled = true ;
33
45
GoogleMapController ? controller;
34
- BitmapDescriptor ? _markerIcon;
46
+ BitmapDescriptor ? _markerIconAsset;
47
+ BitmapDescriptor ? _markerIconBytes;
48
+ final int _markersAmountPerType = 15 ;
35
49
36
50
@override
37
51
Widget build (BuildContext context) {
38
- _createMarkerImageFromAsset (context);
52
+ _createCustomMarkerIconImages (context);
53
+ final Size size = getCurrentMarkerSize ();
39
54
return Column (
40
55
mainAxisAlignment: MainAxisAlignment .spaceEvenly,
41
56
crossAxisAlignment: CrossAxisAlignment .stretch,
42
57
children: < Widget > [
43
- Center (
44
- child: SizedBox (
45
- width: 350.0 ,
46
- height: 300.0 ,
47
- child: GoogleMap (
48
- initialCameraPosition: const CameraPosition (
49
- target: _kMapCenter,
50
- zoom: 7.0 ,
58
+ Column (children: < Widget > [
59
+ Center (
60
+ child: SizedBox (
61
+ width: 350.0 ,
62
+ height: 300.0 ,
63
+ child: GoogleMap (
64
+ initialCameraPosition: const CameraPosition (
65
+ target: _kMapCenter,
66
+ zoom: 7.0 ,
67
+ ),
68
+ markers: _markers,
69
+ onMapCreated: _onMapCreated,
51
70
),
52
- markers: < Marker > {_createMarker ()},
53
- onMapCreated: _onMapCreated,
54
71
),
55
72
),
56
- )
73
+ TextButton (
74
+ onPressed: () => _toggleScaling (context),
75
+ child: Text (_scalingEnabled
76
+ ? 'Disable auto scaling'
77
+ : 'Enable auto scaling' ),
78
+ ),
79
+ if (_scalingEnabled) ...< Widget > [
80
+ Container (
81
+ width: size.width,
82
+ height: size.height,
83
+ color: Colors .red,
84
+ ),
85
+ Text (
86
+ 'Reference box with size of ${size .width } x ${size .height } in logical pixels.' ),
87
+ const SizedBox (height: 10 ),
88
+ TextButton (
89
+ onPressed: () => _toggleCustomSize (context),
90
+ child: Text (_customSizeEnabled
91
+ ? 'Disable custom size'
92
+ : 'Enable custom size' ),
93
+ ),
94
+ if (_customSizeEnabled)
95
+ Row (
96
+ mainAxisAlignment: MainAxisAlignment .spaceEvenly,
97
+ children: < Widget > [
98
+ TextButton (
99
+ onPressed: _markerScale <= 0.5
100
+ ? null
101
+ : () => _decreaseScale (context),
102
+ child: const Text (
103
+ '-' ,
104
+ textScaleFactor: 2 ,
105
+ ),
106
+ ),
107
+ Text ('scale ${_markerScale }x' ),
108
+ TextButton (
109
+ onPressed: _markerScale >= 2.5
110
+ ? null
111
+ : () => _increaseScale (context),
112
+ child: const Text (
113
+ '+' ,
114
+ textScaleFactor: 2 ,
115
+ ),
116
+ ),
117
+ ],
118
+ ),
119
+ ],
120
+ TextButton (
121
+ onPressed: () => _toggleMipMaps (context),
122
+ child: Text (_mipMapsEnabled ? 'Disable mipmaps' : 'Enable mipmaps' ),
123
+ ),
124
+ ])
57
125
],
58
126
);
59
127
}
60
128
61
- Marker _createMarker () {
62
- if (_markerIcon != null ) {
63
- return Marker (
64
- markerId: const MarkerId ('marker_1' ),
65
- position: _kMapCenter,
66
- icon: _markerIcon! ,
67
- );
68
- } else {
69
- return const Marker (
70
- markerId: MarkerId ('marker_1' ),
71
- position: _kMapCenter,
72
- );
73
- }
129
+ Size getCurrentMarkerSize () {
130
+ return _scalingEnabled && _customSizeEnabled
131
+ ? _customSize * _markerScale
132
+ : Size (_markerAssetImageSize, _markerAssetImageSize);
74
133
}
75
134
76
- Future <void > _createMarkerImageFromAsset (BuildContext context) async {
77
- if (_markerIcon == null ) {
78
- final ImageConfiguration imageConfiguration =
79
- createLocalImageConfiguration (context, size: const Size .square (48 ));
80
- BitmapDescriptor .fromAssetImage (
81
- imageConfiguration, 'assets/red_square.png' )
82
- .then (_updateBitmap);
83
- }
135
+ void _toggleMipMaps (BuildContext context) {
136
+ _mipMapsEnabled = ! _mipMapsEnabled;
137
+ _updateMarkerImages (context);
138
+ }
139
+
140
+ void _toggleScaling (BuildContext context) {
141
+ _scalingEnabled = ! _scalingEnabled;
142
+ _updateMarkerImages (context);
143
+ }
144
+
145
+ void _toggleCustomSize (BuildContext context) {
146
+ _customSizeEnabled = ! _customSizeEnabled;
147
+ _updateMarkerImages (context);
148
+ }
149
+
150
+ void _decreaseScale (BuildContext context) {
151
+ _markerScale = max (_markerScale - 0.5 , 0.0 );
152
+ _updateMarkerImages (context);
153
+ }
154
+
155
+ void _increaseScale (BuildContext context) {
156
+ _markerScale = min (_markerScale + 0.5 , 2.5 );
157
+ _updateMarkerImages (context);
158
+ }
159
+
160
+ void _updateMarkerImages (BuildContext context) {
161
+ _updateMarkerAssetImage (context);
162
+ _updateMarkerBytesImage (context);
163
+ _updateMarkers ();
164
+ }
165
+
166
+ Marker _createAssetMarker (int index) {
167
+ final LatLng position =
168
+ LatLng (_kMapCenter.latitude - (index * 0.5 ), _kMapCenter.longitude - 1 );
169
+
170
+ return Marker (
171
+ markerId: MarkerId ('marker_asset_$index ' ),
172
+ position: position,
173
+ icon: _markerIconAsset! ,
174
+ );
175
+ }
176
+
177
+ Marker _createBytesMarker (int index) {
178
+ final LatLng position =
179
+ LatLng (_kMapCenter.latitude - (index * 0.5 ), _kMapCenter.longitude + 1 );
180
+
181
+ return Marker (
182
+ markerId: MarkerId ('marker_bytes_$index ' ),
183
+ position: position,
184
+ icon: _markerIconBytes! ,
185
+ );
84
186
}
85
187
86
- void _updateBitmap (BitmapDescriptor bitmap) {
188
+ void _updateMarkers () {
189
+ final Set <Marker > markers = < Marker > {};
190
+ for (int i = 0 ; i < _markersAmountPerType; i++ ) {
191
+ if (_markerIconAsset != null ) {
192
+ markers.add (_createAssetMarker (i));
193
+ }
194
+ if (_markerIconBytes != null ) {
195
+ markers.add (_createBytesMarker (i));
196
+ }
197
+ }
87
198
setState (() {
88
- _markerIcon = bitmap ;
199
+ _markers = markers ;
89
200
});
90
201
}
91
202
203
+ Future <void > _updateMarkerAssetImage (BuildContext context) async {
204
+ final Size ? size =
205
+ _scalingEnabled && _customSizeEnabled ? getCurrentMarkerSize () : null ;
206
+ final ImageConfiguration imageConfiguration = createLocalImageConfiguration (
207
+ context,
208
+ size: size,
209
+ );
210
+ BitmapDescriptor .createFromAsset (
211
+ imageConfiguration, 'assets/red_square.png' ,
212
+ mipmaps: _mipMapsEnabled,
213
+ imagePixelRatio: _mipMapsEnabled ? null : 1.0 ,
214
+ bitmapScaling:
215
+ _scalingEnabled ? BitmapScaling .auto : BitmapScaling .noScaling)
216
+ .then (_updateAssetBitmap);
217
+ }
218
+
219
+ Future <void > _updateMarkerBytesImage (BuildContext context) async {
220
+ final double devicePixelRatio =
221
+ WidgetsBinding .instance.window.devicePixelRatio;
222
+
223
+ final Size markerSize = getCurrentMarkerSize ();
224
+
225
+ final double ? imagePixelRatio = _scalingEnabled ? devicePixelRatio : null ;
226
+
227
+ // Create canvasSize with physical marker size
228
+ final Size canvasSize = Size (markerSize.width * (imagePixelRatio ?? 1.0 ),
229
+ markerSize.height * (imagePixelRatio ?? 1.0 ));
230
+
231
+ final ByteData bytes = await createCustomMarkerIconImage (size: canvasSize);
232
+
233
+ // Size is used only for custom size
234
+ final Size ? size =
235
+ _scalingEnabled && _customSizeEnabled ? getCurrentMarkerSize () : null ;
236
+
237
+ final BitmapDescriptor bitmap = BitmapDescriptor .createFromBytes (
238
+ bytes.buffer.asUint8List (),
239
+ imagePixelRatio: _customSizeEnabled ? null : imagePixelRatio,
240
+ size: size,
241
+ bitmapScaling:
242
+ _scalingEnabled ? BitmapScaling .auto : BitmapScaling .noScaling);
243
+
244
+ _updateBytesBitmap (bitmap);
245
+ }
246
+
247
+ void _updateAssetBitmap (BitmapDescriptor bitmap) {
248
+ _markerIconAsset = bitmap;
249
+ _updateMarkers ();
250
+ }
251
+
252
+ void _updateBytesBitmap (BitmapDescriptor bitmap) {
253
+ _markerIconBytes = bitmap;
254
+ _updateMarkers ();
255
+ }
256
+
257
+ void _createCustomMarkerIconImages (BuildContext context) {
258
+ if (_markerIconAsset == null ) {
259
+ _updateMarkerAssetImage (context);
260
+ }
261
+
262
+ if (_markerIconBytes == null ) {
263
+ _updateMarkerBytesImage (context);
264
+ }
265
+ }
266
+
92
267
void _onMapCreated (GoogleMapController controllerParam) {
93
268
setState (() {
94
269
controller = controllerParam;
0 commit comments