import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:loading_indicator/loading_indicator.dart'; import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view_gallery.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; ///图片预览控件 class PhotoPreview extends StatefulWidget { List previewImageDatas; int index; String heroTagSuffix; PhotoPreview({Key key, this.previewImageDatas, this.index = 0, this.heroTagSuffix = ""}) : super(key: key); PhotoPreview._showPhotoViewByData({Key key, this.previewImageDatas, this.index = 0, this.heroTagSuffix = ""}) : super(key: key) {} PhotoPreview._showPhotoViewByImages({Key key, List images, this.index = 0, this.heroTagSuffix = ""}) : super(key: key) { if (images != null) { previewImageDatas = List(); for (var img in images) { previewImageDatas.add(PreviewImageData(previewImageType: PreviewImageType.netUrl, data: img)); } } } ///显示类型的一些预览 static showPhotoPreview(BuildContext context, List previewImageDatas, {int currentIndex = 0, String heroTagSuffix}) { Navigator.push( context, MaterialPageRoute( builder: (_) => PhotoPreview._showPhotoViewByData( previewImageDatas: previewImageDatas, index: currentIndex, heroTagSuffix: heroTagSuffix, ))); } ///显示仅仅是一组list类型的图片预览 static showPhotoPreviewByimages(BuildContext context, List images, {int currentIndex = 0, String heroTagSuffix = ""}) { Navigator.push( context, MaterialPageRoute( builder: (_) => PhotoPreview._showPhotoViewByImages( images: images, index: currentIndex, heroTagSuffix: heroTagSuffix, ))); } @override _PhotoPreviewState createState() => _PhotoPreviewState(); } class _PhotoPreviewState extends State { @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return PhotoViewGalleryScreen( images: widget.previewImageDatas, index: widget.index, heroTagSuffix: widget.heroTagSuffix ?? "", ); } @override void dispose() { super.dispose(); } } ///图片预览数据 class PreviewImageData { PreviewImageType previewImageType; String data; bool isSelect; String tag; PreviewImageData({this.previewImageType, this.data, this.isSelect = false, this.tag}); } ///预览类型 enum PreviewImageType { netUrl, ///网络图片 filePath ///本地文件路径 } class PhotoViewGalleryScreen extends StatefulWidget { List images = []; int index = 0; String heroTagSuffix; PhotoViewGalleryScreen({Key key, @required this.images, this.index, this.heroTagSuffix}) : super(key: key); @override _PhotoViewGalleryScreenState createState() => _PhotoViewGalleryScreenState(); } class _PhotoViewGalleryScreenState extends State with AutomaticKeepAliveClientMixin { int currentIndex = 0; PageController pageController; PhotoViewScaleStateController scaleStateController; @override void initState() { scaleStateController = PhotoViewScaleStateController(); // TODO: implement initState pageController = PageController(initialPage: widget?.index ?? 0); currentIndex = widget.index; super.initState(); } @override void dispose() { scaleStateController.dispose(); pageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: Stack( children: [ GestureDetector( onTap: () { Navigator.pop(context); }, child: Container( margin: EdgeInsets.all(1), child: PhotoViewGallery.builder( scrollPhysics: const BouncingScrollPhysics(), builder: (BuildContext context, int index) { return PhotoViewGalleryPageOptions( scaleStateController: scaleStateController, imageProvider: _buildPage(context, index), heroAttributes: widget.heroTagSuffix.isNotEmpty ? PhotoViewHeroAttributes(tag: (widget.images[index].data ?? "") + widget.heroTagSuffix) : null, ); }, itemCount: widget.images.length, loadFailedChild: Container( child: Text("加载失败"), ), loadingBuilder: (context, event) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 48, constraints: BoxConstraints(maxWidth: 48, maxHeight: 48), height: 48, child: LoadingIndicator( indicatorType: Indicator.ballSpinFadeLoader, color: Colors.white, )), ], ); }, backgroundDecoration: BoxDecoration(color: Colors.black), pageController: pageController, enableRotation: true, onPageChanged: (index) { setState(() { currentIndex = index; }); }, ), ), ), Positioned( //图片index显示 top: MediaQuery.of(context).padding.top + 15, width: MediaQuery.of(context).size.width, child: Container( child: Center( child: Text("${currentIndex + 1}/${widget.images.length}", style: TextStyle(color: Colors.white, fontSize: 16)), ), ), ), Positioned( //右上角关闭按钮 right: 10, top: MediaQuery.of(context).padding.top, child: IconButton( icon: Icon( Icons.close, size: 30, color: Colors.white, ), onPressed: () { Navigator.of(context).pop(); }, ), ), ], ), ); } ImageProvider _buildPage(BuildContext context, int index) { var item = widget.images[index]; if (item.previewImageType == PreviewImageType.netUrl) { return CachedNetworkImageProvider(item.data); } else if (item.previewImageType == PreviewImageType.filePath) { return Image.file(File(item.data)).image; } } @override // TODO: implement wantKeepAlive bool get wantKeepAlive => true; } class FadeRoute extends PageRouteBuilder { final Widget page; FadeRoute({this.page}) : super( pageBuilder: ( BuildContext context, Animation animation, Animation secondaryAnimation, ) => page, transitionsBuilder: ( BuildContext context, Animation animation, Animation secondaryAnimation, Widget child, ) => FadeTransition( opacity: animation, child: child, ), ); }