基础库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

photo_preview.dart 7.3 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. import 'dart:io';
  2. import 'package:flutter/material.dart';
  3. import 'package:loading_indicator/loading_indicator.dart';
  4. import 'package:photo_view/photo_view.dart';
  5. import 'package:photo_view/photo_view_gallery.dart';
  6. import 'package:zhiying_comm/zhiying_comm.dart';
  7. ///图片预览控件
  8. class PhotoPreview extends StatefulWidget {
  9. List<PreviewImageData> previewImageDatas;
  10. int index;
  11. String heroTagSuffix;
  12. PhotoPreview(
  13. {Key key,
  14. this.previewImageDatas,
  15. this.index = 0,
  16. this.heroTagSuffix = ""})
  17. : super(key: key);
  18. PhotoPreview._showPhotoViewByData(
  19. {Key key,
  20. this.previewImageDatas,
  21. this.index = 0,
  22. this.heroTagSuffix = ""})
  23. : super(key: key) {
  24. }
  25. PhotoPreview._showPhotoViewByImages(
  26. {Key key, List<String> images, this.index = 0, this.heroTagSuffix = ""})
  27. : super(key: key) {
  28. if (images != null) {
  29. previewImageDatas = List();
  30. for (var img in images) {
  31. previewImageDatas.add(PreviewImageData(
  32. previewImageType: PreviewImageType.netUrl, data: img));
  33. }
  34. }
  35. }
  36. ///显示类型的一些预览
  37. static showPhotoPreview(
  38. BuildContext context, List<PreviewImageData> previewImageDatas,
  39. {int currentIndex = 0, String heroTagSuffix}) {
  40. Navigator.of(context).push(new FadeRoute(
  41. page: PhotoPreview._showPhotoViewByData(
  42. previewImageDatas: previewImageDatas,
  43. index: currentIndex,
  44. heroTagSuffix: heroTagSuffix,
  45. )));
  46. }
  47. ///显示仅仅是一组list<String>类型的图片预览
  48. static showPhotoPreviewByimages(BuildContext context, List<String> images,
  49. {int currentIndex = 0, String heroTagSuffix = ""}) {
  50. Navigator.of(context).push(new FadeRoute(
  51. page: PhotoPreview._showPhotoViewByImages(
  52. images: images,
  53. index: currentIndex,
  54. heroTagSuffix: heroTagSuffix,
  55. )));
  56. }
  57. @override
  58. _PhotoPreviewState createState() => _PhotoPreviewState();
  59. }
  60. class _PhotoPreviewState extends State<PhotoPreview> {
  61. PageController pageController;
  62. @override
  63. void initState() {
  64. pageController = PageController(keepPage: true, initialPage: widget.index);
  65. super.initState();
  66. }
  67. @override
  68. Widget build(BuildContext context) {
  69. return Scaffold(
  70. backgroundColor: Colors.transparent,
  71. body: PhotoViewGalleryScreen(
  72. images: widget.previewImageDatas,
  73. index: widget.index,
  74. controller: pageController,
  75. heroTagSuffix: widget.heroTagSuffix ?? "",
  76. ));
  77. }
  78. }
  79. ///图片预览数据
  80. class PreviewImageData {
  81. PreviewImageType previewImageType;
  82. String data;
  83. bool isSelect;
  84. String tag;
  85. PreviewImageData(
  86. {this.previewImageType, this.data, this.isSelect = false, this.tag});
  87. }
  88. ///预览类型
  89. enum PreviewImageType {
  90. netUrl,
  91. ///网络图片
  92. filePath
  93. ///本地文件路径
  94. }
  95. class PhotoViewGalleryScreen extends StatefulWidget {
  96. List<PreviewImageData> images = [];
  97. int index = 0;
  98. String heroTagSuffix;
  99. PageController controller;
  100. PhotoViewGalleryScreen(
  101. {Key key,
  102. @required this.images,
  103. this.index,
  104. this.controller,
  105. this.heroTagSuffix})
  106. : super(key: key) {
  107. controller = PageController(initialPage: index);
  108. }
  109. @override
  110. _PhotoViewGalleryScreenState createState() => _PhotoViewGalleryScreenState();
  111. }
  112. class _PhotoViewGalleryScreenState extends State<PhotoViewGalleryScreen> {
  113. int currentIndex = 0;
  114. @override
  115. void initState() {
  116. // TODO: implement initState
  117. super.initState();
  118. currentIndex = widget.index;
  119. }
  120. @override
  121. Widget build(BuildContext context) {
  122. return Scaffold(
  123. body: Stack(
  124. children: <Widget>[
  125. GestureDetector(
  126. onTap: () {
  127. Navigator.pop(context);
  128. },
  129. child: Container(
  130. color: Colors.black,
  131. child: PhotoViewGallery.builder(
  132. scrollPhysics: const BouncingScrollPhysics(),
  133. builder: (BuildContext context, int index) {
  134. return PhotoViewGalleryPageOptions(
  135. imageProvider: _buildPage(context, index),
  136. heroAttributes: widget.heroTagSuffix.isNotEmpty
  137. ? PhotoViewHeroAttributes(
  138. tag: (widget.images[index].data ?? "") +
  139. widget.heroTagSuffix)
  140. : null,
  141. );
  142. },
  143. itemCount: widget.images.length,
  144. loadFailedChild: Container(
  145. child: Text("加载失败"),
  146. ),
  147. loadingBuilder: (context,event){
  148. return Column(
  149. mainAxisAlignment: MainAxisAlignment.center,
  150. children: <Widget>[
  151. Container(
  152. width: 48,
  153. constraints: BoxConstraints(maxWidth: 48,maxHeight: 48),
  154. height: 48,
  155. child: LoadingIndicator(indicatorType: Indicator.ballSpinFadeLoader,color: Colors.white,)
  156. ),
  157. ],
  158. );
  159. },
  160. backgroundDecoration: BoxDecoration(color: Colors.black),
  161. pageController: widget.controller,
  162. enableRotation: true,
  163. onPageChanged: (index) {
  164. setState(() {
  165. currentIndex = index;
  166. });
  167. },
  168. )),
  169. ),
  170. Positioned(
  171. //图片index显示
  172. top: MediaQuery.of(context).padding.top + 15,
  173. width: MediaQuery.of(context).size.width,
  174. child: Container(
  175. child: Center(
  176. child: Text("${currentIndex + 1}/${widget.images.length}",
  177. style: TextStyle(color: Colors.white, fontSize: 16)),
  178. ),
  179. ),
  180. ),
  181. Positioned(
  182. //右上角关闭按钮
  183. right: 10,
  184. top: MediaQuery.of(context).padding.top,
  185. child: IconButton(
  186. icon: Icon(
  187. Icons.close,
  188. size: 30,
  189. color: Colors.white,
  190. ),
  191. onPressed: () {
  192. Navigator.of(context).pop();
  193. },
  194. ),
  195. ),
  196. ],
  197. ),
  198. );
  199. }
  200. ImageProvider _buildPage(BuildContext context, int index) {
  201. var item = widget.images[index];
  202. if (item.previewImageType == PreviewImageType.netUrl) {
  203. return CachedNetworkImageProvider(item.data);
  204. } else if (item.previewImageType == PreviewImageType.filePath) {
  205. return Image.file(File(item.data)).image;
  206. }
  207. }
  208. }
  209. class FadeRoute extends PageRouteBuilder {
  210. final Widget page;
  211. FadeRoute({this.page})
  212. : super(
  213. pageBuilder: (
  214. BuildContext context,
  215. Animation<double> animation,
  216. Animation<double> secondaryAnimation,
  217. ) =>
  218. page,
  219. transitionsBuilder: (
  220. BuildContext context,
  221. Animation<double> animation,
  222. Animation<double> secondaryAnimation,
  223. Widget child,
  224. ) =>
  225. FadeTransition(
  226. opacity: animation,
  227. child: child,
  228. ),
  229. );
  230. }