diff --git a/lib/src/layer/tile_layer/animated_tile.dart b/lib/src/layer/tile_layer/animated_tile.dart deleted file mode 100644 index 53380f6eb..000000000 --- a/lib/src/layer/tile_layer/animated_tile.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:flutter/widgets.dart'; -import 'package:flutter_map/flutter_map.dart'; - -class AnimatedTile extends StatefulWidget { - final Tile tile; - final ImageProvider? errorImage; - final TileBuilder? tileBuilder; - - const AnimatedTile({ - Key? key, - required this.tile, - this.errorImage, - required this.tileBuilder, - }) : super(key: key); - - @override - State createState() => _AnimatedTileState(); -} - -class _AnimatedTileState extends State { - bool listenerAttached = false; - - @override - Widget build(BuildContext context) { - final tileWidget = (widget.tile.loadError && widget.errorImage != null) - ? Image( - image: widget.errorImage!, - fit: BoxFit.fill, - ) - : RawImage( - image: widget.tile.imageInfo?.image, - fit: BoxFit.fill, - opacity: widget.tile.animationController); - - return widget.tileBuilder == null - ? tileWidget - : widget.tileBuilder!(context, tileWidget, widget.tile); - } - - @override - void initState() { - super.initState(); - - if (null != widget.tile.animationController) { - widget.tile.animationController!.addListener(_handleChange); - listenerAttached = true; - } - } - - @override - void dispose() { - if (listenerAttached) { - widget.tile.animationController?.removeListener(_handleChange); - } - - super.dispose(); - } - - @override - void didUpdateWidget(AnimatedTile oldWidget) { - super.didUpdateWidget(oldWidget); - - if (!listenerAttached && null != widget.tile.animationController) { - widget.tile.animationController!.addListener(_handleChange); - listenerAttached = true; - } - } - - void _handleChange() { - if (mounted) { - setState(() {}); - } - } -} diff --git a/lib/src/layer/tile_layer/tile.dart b/lib/src/layer/tile_layer/tile.dart index 4cf99afce..8576242ed 100644 --- a/lib/src/layer/tile_layer/tile.dart +++ b/lib/src/layer/tile_layer/tile.dart @@ -16,7 +16,7 @@ class Tile { DateTime? loaded; late DateTime loadStarted; - AnimationController? animationController; + final AnimationController? animationController; double get opacity => animationController == null ? (active ? 1.0 : 0.0) @@ -33,12 +33,18 @@ class Tile { required this.coords, required this.tilePos, required this.imageProvider, + required final TickerProvider vsync, this.tileReady, this.current = false, this.active = false, this.retain = false, this.loadError = false, - }); + final Duration? duration, + }) : animationController = duration != null + ? AnimationController(duration: duration, vsync: vsync) + : null { + animationController?.addStatusListener(_onAnimateEnd); + } void loadTileImage() { loadStarted = DateTime.now(); @@ -78,15 +84,9 @@ class Tile { _imageStream?.removeListener(_listener); } - void startFadeInAnimation(Duration duration, TickerProvider vsync, - {double? from}) { - animationController?.removeStatusListener(_onAnimateEnd); - animationController?.dispose(); - - animationController = AnimationController(duration: duration, vsync: vsync) - ..addStatusListener(_onAnimateEnd); - - animationController!.forward(from: from); + void startFadeInAnimation({double? from}) { + animationController?.reset(); + animationController?.forward(from: from); } void _onAnimateEnd(AnimationStatus status) { @@ -96,14 +96,14 @@ class Tile { } void _tileOnLoad(ImageInfo imageInfo, bool synchronousCall) { - if (null != tileReady) { + if (tileReady != null) { this.imageInfo = imageInfo; tileReady!(coords, null, this); } } void _tileOnError(dynamic exception, StackTrace? stackTrace) { - if (null != tileReady) { + if (tileReady != null) { tileReady!( coords, exception ?? 'Unknown exception during loadTileImage', this); } diff --git a/lib/src/layer/tile_layer/tile_layer.dart b/lib/src/layer/tile_layer/tile_layer.dart index 5a8e71ebf..af8dd1f73 100644 --- a/lib/src/layer/tile_layer/tile_layer.dart +++ b/lib/src/layer/tile_layer/tile_layer.dart @@ -432,7 +432,7 @@ class _TileLayerState extends State with TickerProviderStateMixin { final tileWidgets = [ for (var tile in tilesToRender) - TileWidget( + AnimatedTile( tile: tile, size: _tileSize, tileTransformation: zoomToTransformation[tile.coords.z] ?? @@ -633,6 +633,8 @@ class _TileLayerState extends State with TickerProviderStateMixin { imageProvider: widget.tileProvider.getImage(coords.wrap(_wrapX, _wrapY), widget), tileReady: _tileReady, + vsync: this, + duration: widget.tileFadeInDuration, ); _tileManager.add(coords, newTile); @@ -712,11 +714,7 @@ class _TileLayerState extends State with TickerProviderStateMixin { (tile.loadError && null == widget.errorImage)) { tile.active = true; } else { - tile.startFadeInAnimation( - widget.tileFadeInDuration!, - this, - from: fadeInStart, - ); + tile.startFadeInAnimation(from: fadeInStart); } if (mounted) { diff --git a/lib/src/layer/tile_layer/tile_widget.dart b/lib/src/layer/tile_layer/tile_widget.dart index 68af0cdcc..282040a4b 100644 --- a/lib/src/layer/tile_layer/tile_widget.dart +++ b/lib/src/layer/tile_layer/tile_widget.dart @@ -1,16 +1,15 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_map/flutter_map.dart'; -import 'package:flutter_map/src/layer/tile_layer/animated_tile.dart'; import 'package:flutter_map/src/layer/tile_layer/tile_transformation.dart'; -class TileWidget extends StatelessWidget { +class AnimatedTile extends StatelessWidget { final Tile tile; final CustomPoint size; final TileTransformation tileTransformation; final ImageProvider? errorImage; final TileBuilder? tileBuilder; - const TileWidget({ + const AnimatedTile({ required this.tile, required this.size, required this.tileTransformation, @@ -26,16 +25,27 @@ class TileWidget extends StatelessWidget { final num width = size.x * tileTransformation.scale; final num height = size.y * tileTransformation.scale; + Widget tileWidget; + if (tile.loadError && errorImage != null) { + tileWidget = Image(image: errorImage!); + } else if (tile.animationController == null) { + tileWidget = RawImage(image: tile.imageInfo?.image, fit: BoxFit.fill); + } else { + tileWidget = AnimatedBuilder( + animation: tile.animationController!, + builder: (context, child) => RawImage( + image: tile.imageInfo?.image, + fit: BoxFit.fill, + opacity: tile.animationController!), + ); + } + return Positioned( left: pos.x.toDouble(), top: pos.y.toDouble(), width: width.toDouble(), height: height.toDouble(), - child: AnimatedTile( - tile: tile, - errorImage: errorImage, - tileBuilder: tileBuilder, - ), + child: tileBuilder?.call(context, tileWidget, tile) ?? tileWidget, ); } }