Skip to content

Commit

Permalink
add Tile Builder api
Browse files Browse the repository at this point in the history
  • Loading branch information
maRci002 committed Sep 16, 2020
1 parent edd283e commit 793aab5
Show file tree
Hide file tree
Showing 6 changed files with 345 additions and 41 deletions.
2 changes: 2 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_map_example/pages/tile_builder_example.dart';

import './pages/animated_map_controller.dart';
import './pages/circle.dart';
Expand Down Expand Up @@ -58,6 +59,7 @@ class MyApp extends StatelessWidget {
CustomCrsPage.route: (context) => CustomCrsPage(),
LiveLocationPage.route: (context) => LiveLocationPage(),
TileLoadingErrorHandle.route: (context) => TileLoadingErrorHandle(),
TileBuilderPage.route: (context) => TileBuilderPage(),
},
);
}
Expand Down
142 changes: 142 additions & 0 deletions example/lib/pages/tile_builder_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong/latlong.dart';

import '../widgets/drawer.dart';

class TileBuilderPage extends StatefulWidget {
static const String route = '/tile_builder_example';

@override
_TileBuilderPageState createState() => _TileBuilderPageState();
}

class _TileBuilderPageState extends State<TileBuilderPage> {
var darkMode = false;
var loadingTime = false;
var showCoords = false;
var grid = false;

// mix of [coordinateDebugTileBuilder] and [loadingTimeDebugTileBuilder] from tile_builder.dart
Widget tileBuilder(BuildContext context, Widget tileWidget, Tile tile) {
final coords = tile.coords;

return Container(
decoration: BoxDecoration(
border: grid ? Border.all() : null,
),
child: Stack(
fit: StackFit.passthrough,
children: [
tileWidget,
if (loadingTime || showCoords)
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (showCoords)
Text(
'${coords.x.floor()} : ${coords.y.floor()} : ${coords.z.floor()}',
style: Theme.of(context).textTheme.headline5,
),
if (loadingTime)
Text(
tile.loaded == null
? 'Loading'
// sometimes result is negative which shouldn't happen, abs() corrects it
: '${(tile.loaded.millisecond - tile.loadStarted.millisecond).abs()} ms',
style: Theme.of(context).textTheme.headline5,
),
],
),
],
),
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Tile builder')),
drawer: buildDrawer(context, TileBuilderPage.route),
floatingActionButton: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
FloatingActionButton.extended(
heroTag: 'grid',
label: Text(
grid ? 'Hide grid' : 'Show grid',
textAlign: TextAlign.center,
),
icon: Icon(grid ? Icons.grid_off : Icons.grid_on),
onPressed: () => setState(() => grid = !grid),
),
SizedBox(height: 8),
FloatingActionButton.extended(
heroTag: 'coords',
label: Text(
showCoords ? 'Hide coords' : 'Show coords',
textAlign: TextAlign.center,
),
icon: Icon(showCoords ? Icons.unarchive : Icons.bug_report),
onPressed: () => setState(() => showCoords = !showCoords),
),
SizedBox(height: 8),
FloatingActionButton.extended(
heroTag: 'ms',
label: Text(
loadingTime ? 'Hide loading time' : 'Show loading time',
textAlign: TextAlign.center,
),
icon: Icon(loadingTime ? Icons.timer_off : Icons.timer),
onPressed: () => setState(() => loadingTime = !loadingTime),
),
SizedBox(height: 8),
FloatingActionButton.extended(
heroTag: 'dark-light',
label: Text(
darkMode ? 'Light mode' : 'Dark mode',
textAlign: TextAlign.center,
),
icon: Icon(darkMode ? Icons.brightness_high : Icons.brightness_2),
onPressed: () => setState(() => darkMode = !darkMode),
),
],
),
body: Padding(
padding: EdgeInsets.all(8.0),
child: FlutterMap(
options: MapOptions(
center: LatLng(51.5, -0.09),
zoom: 5.0,
),
layers: [
TileLayerOptions(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'],
tileProvider: NonCachingNetworkTileProvider(),
tileBuilder: tileBuilder,
tilesContainerBuilder:
darkMode ? darkModeTilesContainerBuilder : null,
),
MarkerLayerOptions(
markers: <Marker>[
Marker(
width: 80.0,
height: 80.0,
point: LatLng(51.5, -0.09),
builder: (ctx) => Container(
child: FlutterLogo(
colors: Colors.blue,
key: ObjectKey(Colors.blue),
),
),
),
],
)
],
),
),
);
}
}
57 changes: 30 additions & 27 deletions example/lib/widgets/drawer.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_map_example/pages/tile_builder_example.dart';

import '../pages/animated_map_controller.dart';
import '../pages/circle.dart';
Expand Down Expand Up @@ -157,33 +158,35 @@ Drawer buildDrawer(BuildContext context, String currentRoute) {
OverlayImagePage.route,
currentRoute,
),
ListTile(
title: const Text('Sliding Map'),
selected: currentRoute == SlidingMapPage.route,
onTap: () =>
Navigator.pushReplacementNamed(context, SlidingMapPage.route),
),
ListTile(
title: const Text('Widgets'),
selected: currentRoute == WidgetsPage.route,
onTap: () {
Navigator.pushReplacementNamed(context, WidgetsPage.route);
},
),
ListTile(
title: const Text('Live Location Update'),
selected: currentRoute == LiveLocationPage.route,
onTap: () {
Navigator.pushReplacementNamed(context, LiveLocationPage.route);
},
),
ListTile(
title: const Text('Tile loading error handle'),
selected: currentRoute == TileLoadingErrorHandle.route,
onTap: () {
Navigator.pushReplacementNamed(
context, TileLoadingErrorHandle.route);
},
_buildMenuItem(
context,
const Text('Sliding Map'),
SlidingMapPage.route,
currentRoute,
),
_buildMenuItem(
context,
const Text('Widgets'),
WidgetsPage.route,
currentRoute,
),
_buildMenuItem(
context,
const Text('Live Location Update'),
LiveLocationPage.route,
currentRoute,
),
_buildMenuItem(
context,
const Text('Tile loading error handle'),
TileLoadingErrorHandle.route,
currentRoute,
),
_buildMenuItem(
context,
const Text('Tile builder'),
TileBuilderPage.route,
currentRoute,
),
],
),
Expand Down
1 change: 1 addition & 0 deletions lib/flutter_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export 'package:flutter_map/src/layer/marker_layer.dart';
export 'package:flutter_map/src/layer/overlay_image_layer.dart';
export 'package:flutter_map/src/layer/polygon_layer.dart';
export 'package:flutter_map/src/layer/polyline_layer.dart';
export 'package:flutter_map/src/layer/tile_builder/tile_builder.dart';
export 'package:flutter_map/src/layer/tile_layer.dart';
export 'package:flutter_map/src/layer/tile_provider/mbtiles_image_provider.dart';
export 'package:flutter_map/src/layer/tile_provider/tile_provider.dart';
Expand Down
124 changes: 124 additions & 0 deletions lib/src/layer/tile_builder/tile_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';

typedef TileBuilder = Widget Function(
BuildContext context, Widget tileWidget, Tile tile);

typedef TilesContainerBuilder = Widget Function(
BuildContext context, Widget tilesContainer, List<Tile> tiles);

/// Applies inversion color matrix on Tiles container which may simulate Dark mode.
final TilesContainerBuilder darkModeTilesContainerBuilder =
(BuildContext context, Widget tilesContainer, List<Tile> tiles) {
return ColorFiltered(
colorFilter: const ColorFilter.matrix(<double>[
-1,
0,
0,
0,
255,
0,
-1,
0,
0,
255,
0,
0,
-1,
0,
255,
0,
0,
0,
1,
0,
]),
child: tilesContainer,
);
};

/// Applies inversion color matrix on Tiles which may simulate Dark mode.
/// [darkModeTilesContainerBuilder] is better at performance because it applies color matrix on the container instead of on every Tile
final TileBuilder darkModeTileBuilder =
(BuildContext context, Widget tileWidget, Tile tile) {
return ColorFiltered(
colorFilter: const ColorFilter.matrix(<double>[
-1,
0,
0,
0,
255,
0,
-1,
0,
0,
255,
0,
0,
-1,
0,
255,
0,
0,
0,
1,
0,
]),
child: tileWidget,
);
};

/// Shows coordinates over Tiles
final TileBuilder coordinateDebugTileBuilder =
(BuildContext context, Widget tileWidget, Tile tile) {
final coords = tile.coords;
final readableKey =
'${coords.x.floor()} : ${coords.y.floor()} : ${coords.z.floor()}';

return Container(
decoration: BoxDecoration(
border: Border.all(),
),
child: Stack(
fit: StackFit.passthrough,
children: [
tileWidget,
Center(
child: Text(
readableKey,
style: Theme.of(context).textTheme.headline5,
),
),
],
),
);
};

/// Shows the Tile loading time in ms
final TileBuilder loadingTimeDebugTileBuilder =
(BuildContext context, Widget tileWidget, Tile tile) {
var loadStarted = tile.loadStarted;
var loaded = tile.loaded;

final time = loaded == null
? 'Loading'
: '${(loaded.millisecond - loadStarted.millisecond).abs()} ms';

return Container(
decoration: BoxDecoration(
border: Border.all(),
),
child: Stack(
fit: StackFit.passthrough,
children: [
tileWidget,
Center(
child: Text(
time,
style: Theme.of(context).textTheme.headline5,
),
),
],
),
);
};
Loading

0 comments on commit 793aab5

Please sign in to comment.