import 'dart:io'; import 'package:ansu_ui/extension/num_extension.dart'; import 'package:flutter/material.dart'; class PhotoViewer extends StatefulWidget { final File? file; final String? net; final String tag; static fromFile(BuildContext context, {required String tag, required File file}) { Navigator.push( context, PageRouteBuilder( pageBuilder: (context, animation, secondAnimation) { return PhotoViewer.toFile(file: file, tag: tag); }, opaque: false, transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition(opacity: animation, child: child); }, ), ); } static fromNet(BuildContext context, {required String tag, required String net}) { Navigator.push( context, PageRouteBuilder( pageBuilder: (context, animation, secondAnimation) { return PhotoViewer.toNet(net: net, tag: tag); }, opaque: false, transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition(opacity: animation, child: child); }, ), ); } PhotoViewer.toFile({ Key? key, this.file, required this.tag, }) : net = null, super(key: key); PhotoViewer.toNet({Key? key, required this.tag, this.net}) : file = null, super(key: key); @override _PhotoViewerState createState() => _PhotoViewerState(); } class _PhotoViewerState extends State with SingleTickerProviderStateMixin { TransformationController _controller = TransformationController(); Animation? _animationReset; late AnimationController _controllerReset; void reset() { _controllerReset.reset(); _animationReset = Matrix4Tween( begin: _controller.value, end: Matrix4.identity(), ).animate(_controllerReset); _animationReset!.addListener(_onAnimateReset); _controllerReset.forward(); } void _onAnimateReset() { _controller.value = _animationReset!.value; if (!_controllerReset.isAnimating) { _animationReset?.removeListener(_onAnimateReset); _animationReset = null; _controllerReset.reset(); } } @override void initState() { _controllerReset = AnimationController(vsync: this, duration: Duration(milliseconds: 400)); super.initState(); } @override void dispose() { _controllerReset.dispose(); _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () => Navigator.pop(context), onDoubleTap: () => reset(), child: Scaffold( backgroundColor: Colors.black54, body: InteractiveViewer( transformationController: _controller, boundaryMargin: 100.edge, child: Container( width: double.infinity, height: double.infinity, alignment: Alignment.center, child: Hero( tag: widget.tag, child: widget.file != null ? Image.file(widget.file!) : Image.network(widget.net!), ), ), ), ), ); } }