Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
dart
  • Loading branch information
Chris Yang committed Jan 14, 2021
commit e459267272e2a29a4a296c38b6e87acfa6ab7453
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import 'place_polygon.dart';
import 'place_polyline.dart';
import 'scrolling_map.dart';
import 'snapshot.dart';
import 'tile_overlay.dart';

final List<GoogleMapExampleAppPage> _allPages = <GoogleMapExampleAppPage>[
MapUiPage(),
Expand All @@ -36,6 +37,7 @@ final List<GoogleMapExampleAppPage> _allPages = <GoogleMapExampleAppPage>[
PaddingPage(),
SnapshotPage(),
LiteModePage(),
TileOverlayPage(),
];

class MapsDemo extends StatelessWidget {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Copyright 2018 The Chromium 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:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

import 'page.dart';

class TileOverlayPage extends GoogleMapExampleAppPage {
TileOverlayPage() : super(const Icon(Icons.map), 'Tile overlay');

@override
Widget build(BuildContext context) {
return const TileOverlayBody();
}
}

class TileOverlayBody extends StatefulWidget {
const TileOverlayBody();

@override
State<StatefulWidget> createState() => TileOverlayBodyState();
}

class TileOverlayBodyState extends State<TileOverlayBody> {
TileOverlayBodyState();

GoogleMapController controller;
TileOverlay _tileOverlay;

void _onMapCreated(GoogleMapController controller) {
this.controller = controller;
}

@override
void dispose() {
super.dispose();
}

void _removeTileOverlay() {
setState(() {
_tileOverlay = null;
});
}

void _addTileOverlay() {
final TileOverlay tileOverlay = TileOverlay(
tileOverlayId: TileOverlayId("tile_overlay_1"),
tileProvider: DebugTileProvider(),
);
setState(() {
_tileOverlay = tileOverlay;
});
}

void _clearTileCache() {
if (_tileOverlay != null && controller != null) {
controller.clearTileCache(_tileOverlay.tileOverlayId);
}
}

@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Center(
child: SizedBox(
width: 350.0,
height: 300.0,
child: GoogleMap(
initialCameraPosition: const CameraPosition(
target: LatLng(59.935460, 30.325177),
zoom: 7.0,
),
tileOverlays:
_tileOverlay != null ? <TileOverlay>{_tileOverlay} : null,
onMapCreated: _onMapCreated,
),
),
),
FlatButton(
child: const Text('Add tile overlay'),
onPressed: _addTileOverlay,
),
FlatButton(
child: const Text('Remove tile overlay'),
onPressed: _removeTileOverlay,
),
FlatButton(
child: const Text('Clear tile cache'),
onPressed: _clearTileCache,
),
],
);
}
}

class DebugTileProvider implements TileProvider {
DebugTileProvider() {
boxPaint.isAntiAlias = true;
boxPaint.color = Colors.blue;
boxPaint.strokeWidth = 2.0;
boxPaint.style = PaintingStyle.stroke;
}

static const int width = 100;
static const int height = 100;
static final Paint boxPaint = Paint();
static final TextStyle textStyle = TextStyle(
color: Colors.red,
fontSize: 20,
);

@override
Future<Tile> getTile(int x, int y, int zoom) async {
final ui.PictureRecorder recorder = ui.PictureRecorder();
final Canvas canvas = Canvas(recorder);
final TextSpan textSpan = TextSpan(
text: "$x,$y",
style: textStyle,
);
final TextPainter textPainter = TextPainter(
text: textSpan,
textDirection: TextDirection.ltr,
);
textPainter.layout(
minWidth: 0.0,
maxWidth: width.toDouble(),
);
final Offset offset = const Offset(0, 0);
textPainter.paint(canvas, offset);
canvas.drawRect(
Rect.fromLTRB(0, 0, width.toDouble(), width.toDouble()), boxPaint);
final ui.Picture picture = recorder.endRecording();
final Uint8List byteData = await picture
.toImage(width, height)
.then((ui.Image image) =>
image.toByteData(format: ui.ImageByteFormat.png))
.then((ByteData byteData) => byteData.buffer.asUint8List());
return Tile(width, height, byteData);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ export 'package:google_maps_flutter_platform_interface/google_maps_flutter_platf
PolygonId,
Polyline,
PolylineId,
ScreenCoordinate;
ScreenCoordinate,
Tile,
TileOverlayId,
TileOverlay,
TileProvider;

part 'src/controller.dart';
part 'src/google_map.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class GoogleMapController {
@required this.mapId,
}) : assert(_googleMapsFlutterPlatform != null) {
_connectStreams(mapId);
_googleMapsFlutterPlatform.setGetTileCallback(
mapId: mapId, callback: _googleMapState._onGetTile);
}

/// Initialize control of a [GoogleMap] with [id].
Expand Down Expand Up @@ -152,6 +154,32 @@ class GoogleMapController {
mapId: mapId);
}

/// Updates tile overlays configuration.
///
/// Change listeners are notified once the update has been made on the
/// platform side.
///
/// The returned [Future] completes after listeners have been notified.
Future<void> _updateTileOverlays(TileOverlayUpdates tileOverlayUpdates) {
assert(tileOverlayUpdates != null);
return _googleMapsFlutterPlatform.updateTileOverlays(tileOverlayUpdates,
mapId: mapId);
}

/// Clears the tile cache so that all tiles will be requested again from the
/// [TileProvider].
///
/// The current tiles from this tile overlay will also be
/// cleared from the map after calling this method. The API maintains a small
/// in-memory cache of tiles. If you want to cache tiles for longer, you
/// should implement an on-disk cache.
Future<void> clearTileCache(TileOverlayId tileOverlayId) async {
assert(tileOverlayId != null);
return _googleMapsFlutterPlatform.clearTileCache(tileOverlayId,
mapId: mapId);
}


/// Starts an animated change of the map camera position.
///
/// The returned [Future] completes after the change has been started on the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class GoogleMap extends StatefulWidget {
this.polylines,
this.circles,
this.onCameraMoveStarted,
this.tileOverlays,
this.onCameraMove,
this.onCameraIdle,
this.onTap,
Expand Down Expand Up @@ -120,6 +121,9 @@ class GoogleMap extends StatefulWidget {
/// Circles to be placed on the map.
final Set<Circle> circles;

/// Tile overlays to be placed on the map.
final Set<TileOverlay> tileOverlays;

/// Called when the camera starts moving.
///
/// This can be initiated by the following:
Expand Down Expand Up @@ -220,6 +224,7 @@ class _GoogleMapState extends State<GoogleMap> {
Map<PolygonId, Polygon> _polygons = <PolygonId, Polygon>{};
Map<PolylineId, Polyline> _polylines = <PolylineId, Polyline>{};
Map<CircleId, Circle> _circles = <CircleId, Circle>{};
Map<TileOverlayId, TileOverlay> _tileOverlays = <TileOverlayId, TileOverlay>{};
_GoogleMapOptions _googleMapOptions;

@override
Expand All @@ -232,6 +237,7 @@ class _GoogleMapState extends State<GoogleMap> {
'polylinesToAdd': serializePolylineSet(widget.polylines),
'circlesToAdd': serializeCircleSet(widget.circles),
'_webOnlyMapCreationId': _webOnlyMapCreationId,
'tileOverlaysToAdd': serializeTileOverlaySet(widget.tileOverlays),
};

return _googleMapsFlutterPlatform.buildView(
Expand All @@ -249,6 +255,7 @@ class _GoogleMapState extends State<GoogleMap> {
_polygons = keyByPolygonId(widget.polygons);
_polylines = keyByPolylineId(widget.polylines);
_circles = keyByCircleId(widget.circles);
_tileOverlays = keyTileOverlayId(widget.tileOverlays);
}

@override
Expand All @@ -266,6 +273,7 @@ class _GoogleMapState extends State<GoogleMap> {
_updatePolygons();
_updatePolylines();
_updateCircles();
_updateTileOverlays();
}

void _updateOptions() async {
Expand Down Expand Up @@ -313,6 +321,14 @@ class _GoogleMapState extends State<GoogleMap> {
_circles = keyByCircleId(widget.circles);
}

void _updateTileOverlays() async {
final GoogleMapController controller = await _controller.future;
// ignore: unawaited_futures
controller._updateTileOverlays(TileOverlayUpdates.from(
_tileOverlays.values.toSet(), widget.tileOverlays));
_tileOverlays = keyTileOverlayId(widget.tileOverlays);
}

Future<void> onPlatformViewCreated(int id) async {
final GoogleMapController controller = await GoogleMapController.init(
id,
Expand Down Expand Up @@ -376,6 +392,21 @@ class _GoogleMapState extends State<GoogleMap> {
widget.onLongPress(position);
}
}

// Returns the [Tile] from an added [TileOverlay].
//
// If the TileOverlay or his TileProvider is not found,
// a [TileProvider.noTile] is returned.
Future<Tile> _onGetTile(
String tileOverlayIdRaw, int x, int y, int zoom) async {
assert(tileOverlayIdRaw != null);
final TileOverlayId tileOverlayId = TileOverlayId(tileOverlayIdRaw);
final TileOverlay tileOverlay = _tileOverlays[tileOverlayId];
if (tileOverlay == null || tileOverlay.tileProvider == null) {
return null;
}
return await tileOverlay.tileProvider.getTile(x, y, zoom);
}
}

/// Configuration options for the GoogleMaps user interface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ dependencies:
flutter:
sdk: flutter
flutter_plugin_android_lifecycle: ^1.0.0
google_maps_flutter_platform_interface: ^1.1.0
google_maps_flutter_platform_interface:
path: ../google_maps_flutter_platform_interface
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: update to version dep before landing


dev_dependencies:
flutter_test:
Expand Down
Loading