import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_gifimage/flutter_gifimage.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:visibility_detector/visibility_detector.dart'; class RainRadar extends StatefulWidget { const RainRadar({Key? key}) : super(key: key); @override State createState() => _RainRadarState(); } class _RainRadarState extends State with SingleTickerProviderStateMixin { late GifController controller; double controllerValue = 0; bool _gifLoaded = false; late Uint8List _gifBytes; @override void initState() { super.initState(); loadGif(); controller = GifController(vsync: this); controller.addListener(() { setState(() { controllerValue = controller.value; }); }); } @override void dispose() { controller.dispose(); super.dispose(); } void loadGif() async { imageCache.clear(); await DefaultCacheManager() .getSingleFile('https://www.dwd.de/DWD/wetter/radar/radarvhs.gif') .then((gif) { setState(() { _gifBytes = gif.readAsBytesSync(); _gifLoaded = true; }); }); } Widget _showGif() { return Column(children: [ Padding( padding: const EdgeInsets.all(10), child: VisibilityDetector( key: const Key('gif-key'), onVisibilityChanged: (visibilityInfo) { if (visibilityInfo.visibleFraction > 0) { controller.animateTo(24, duration: const Duration(seconds: 15)); } }, child: GifImage(controller: controller, image: MemoryImage(_gifBytes)), )), Row(mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () { int duration = ((15 / 24) * (24 - controller.value)).round(); controller.animateTo(24, duration: Duration(seconds: duration)); }, child: const Icon(Icons.play_arrow)), const SizedBox(width: 10), ElevatedButton( onPressed: () { controller.stop(); }, child: const Icon(Icons.pause)), ]), Slider( onChanged: (v) { controller.value = v; setState(() {}); }, max: 24, min: 0, value: controllerValue, ) ]); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Rain Radar'), ), body: RefreshIndicator( onRefresh: (() { return Future(() { setState(() { _gifLoaded = false; }); loadGif(); }); }), child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), child: _gifLoaded ? _showGif() : Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: const [ SizedBox( height: 50, ), Center(child: CircularProgressIndicator()) ])))); } }