Няма описание

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. library photo;
  2. import 'dart:async';
  3. import 'dart:io';
  4. import 'package:flutter/material.dart';
  5. import 'package:image_picker/image_picker.dart';
  6. import 'package:photo/src/entity/_theme.dart';
  7. import 'package:photo/src/ui/page/photo_list_page.dart';
  8. import 'package:photo/src/ui/page/photo_main_page.dart';
  9. import 'package:photo_manager/photo_manager.dart';
  10. import 'package:photo/src/delegate/badge_delegate.dart';
  11. import 'package:photo/src/delegate/checkbox_builder_delegate.dart';
  12. import 'package:photo/src/delegate/loading_delegate.dart';
  13. import 'package:photo/src/delegate/sort_delegate.dart';
  14. import 'package:photo/src/entity/options.dart';
  15. import 'package:photo/src/provider/i18n_provider.dart';
  16. import 'package:photo/src/ui/dialog/not_permission_dialog.dart';
  17. import 'package:provider/provider.dart';
  18. import 'src/provider/config_provider.dart';
  19. export 'package:photo/src/delegate/checkbox_builder_delegate.dart';
  20. export 'package:photo/src/delegate/loading_delegate.dart';
  21. export 'package:photo/src/delegate/sort_delegate.dart';
  22. export 'package:photo/src/provider/i18n_provider.dart'
  23. show I18NCustomProvider, I18nProvider, CNProvider, ENProvider;
  24. export 'package:photo/src/entity/options.dart' show PickType, PickedEntity;
  25. export 'package:photo/src/delegate/badge_delegate.dart';
  26. export 'package:photo/src/entity/_theme.dart';
  27. export 'package:image_picker/image_picker.dart' show CameraDevice;
  28. export 'package:photo_manager/photo_manager.dart' show AssetEntity;
  29. class PhotoPicker {
  30. static PhotoPicker _instance;
  31. PhotoPicker._();
  32. factory PhotoPicker() {
  33. _instance ??= PhotoPicker._();
  34. return _instance;
  35. }
  36. static const String rootRouteName = "photo_picker_image";
  37. /// 没有授予权限的时候,会开启一个dialog去帮助用户去应用设置页面开启权限
  38. /// 确定开启设置页面,取消关闭弹窗,无论选择什么,返回值都是null
  39. /// 当用户给予权限后
  40. ///
  41. /// 返回一个[PickedEntity] 内有[AssetEntity]以及[isFullImage]
  42. ///
  43. /// 当用户取消时[AssetEntity]返回一个空数组
  44. ///
  45. /// [photoPathList] 一旦设置 则 [pickType]参数无效
  46. ///
  47. /// [pickedAssetList] 已选择的asset
  48. ///
  49. /// 关于参数可以查看readme文档介绍
  50. static Future<PickedEntity> pickAsset({
  51. @required BuildContext context,
  52. int rowCount = 4,
  53. int maxSelected = 9,
  54. double padding = 1,
  55. double itemRadio = 1.0,
  56. int thumbSize = 180,
  57. PhotoTheme theme,
  58. I18nProvider provider = I18nProvider.chinese,
  59. SortDelegate sortDelegate,
  60. LoadingDelegate loadingDelegate,
  61. PickType pickType = PickType.all,
  62. List<AssetPathEntity> photoPathList,
  63. List<AssetEntity> pickedAssetList,
  64. }) {
  65. assert(maxSelected != 0, "maxSelected must be not 0");
  66. assert(provider != null, "provider must be not null");
  67. assert(context != null, "context must be not null");
  68. assert(pickType != null, "pickType must be not null");
  69. sortDelegate ??= SortDelegate.common;
  70. loadingDelegate ??= DefaultLoadingDelegate();
  71. var options = Options(
  72. rowCount: rowCount,
  73. maxSelected: maxSelected,
  74. itemRadio: itemRadio,
  75. padding: padding,
  76. theme: theme ?? PhotoTheme.fallback(context),
  77. thumbSize: thumbSize,
  78. sortDelegate: sortDelegate,
  79. checkBoxBuilderDelegate: DefaultCheckBoxBuilderDelegate(),
  80. loadingDelegate: loadingDelegate,
  81. badgeDelegate: DefaultBadgeDelegate(),
  82. pickType: pickType,
  83. );
  84. return PhotoPicker()._pickAsset(
  85. context,
  86. options,
  87. provider,
  88. photoPathList,
  89. pickedAssetList,
  90. );
  91. }
  92. static Future<AssetEntity> pickSingleAsset({
  93. @required BuildContext context,
  94. int rowCount = 4,
  95. double padding = 1,
  96. double itemRadio = 1.0,
  97. int thumbSize = 180,
  98. PhotoTheme theme,
  99. I18nProvider provider = I18nProvider.chinese,
  100. SortDelegate sortDelegate,
  101. LoadingDelegate loadingDelegate,
  102. PickType pickType = PickType.all,
  103. List<AssetPathEntity> photoPathList,
  104. }) async {
  105. final PickedEntity result = await PhotoPicker.pickAsset(
  106. context: context,
  107. rowCount: rowCount,
  108. maxSelected: 1,
  109. padding: padding,
  110. itemRadio: itemRadio,
  111. thumbSize: thumbSize,
  112. theme: theme,
  113. provider: provider,
  114. sortDelegate: sortDelegate,
  115. loadingDelegate: loadingDelegate,
  116. pickType: pickType,
  117. photoPathList: photoPathList,
  118. pickedAssetList: [],
  119. );
  120. if (result.asset.isNotEmpty) {
  121. return result.asset[0];
  122. }
  123. return null;
  124. }
  125. static Future<File> pickCamera({
  126. double maxWidth,
  127. double maxHeight,
  128. int imageQuality,
  129. CameraDevice preferredCameraDevice = CameraDevice.rear,
  130. }) async {
  131. return ImagePicker.pickImage(
  132. source: ImageSource.camera,
  133. maxWidth: maxWidth,
  134. maxHeight: maxHeight,
  135. imageQuality: imageQuality,
  136. preferredCameraDevice: preferredCameraDevice,
  137. );
  138. }
  139. Future<PickedEntity> _pickAsset(
  140. BuildContext context,
  141. Options options,
  142. I18nProvider provider,
  143. List<AssetPathEntity> photoList,
  144. List<AssetEntity> pickedAssetList,
  145. ) async {
  146. await requestPermission(context, provider: provider);
  147. return _openGalleryContentPage(
  148. context,
  149. options,
  150. provider,
  151. photoList,
  152. pickedAssetList,
  153. );
  154. }
  155. static Widget buildGallery({
  156. @required BuildContext context,
  157. double padding = 1,
  158. int maxSelected = 9,
  159. int thumbSize = 180,
  160. double itemRadio = 1.0,
  161. PhotoTheme theme,
  162. I18nProvider provider = I18nProvider.chinese,
  163. SortDelegate sortDelegate,
  164. LoadingDelegate loadingDelegate,
  165. PickType pickType = PickType.all,
  166. List<AssetPathEntity> photoPathList,
  167. List<AssetEntity> pickedAssetList,
  168. bool isFullImage = false,
  169. void Function(PickedEntity value) onSelected,
  170. }) {
  171. sortDelegate ??= SortDelegate.common;
  172. loadingDelegate ??= DefaultLoadingDelegate();
  173. var options = ListOptions(
  174. padding: padding,
  175. maxSelected: maxSelected,
  176. itemRadio: itemRadio,
  177. theme: theme ?? PhotoTheme.fallback(context),
  178. thumbSize: thumbSize,
  179. sortDelegate: sortDelegate,
  180. checkBoxBuilderDelegate: DefaultCheckBoxBuilderDelegate(),
  181. loadingDelegate: loadingDelegate,
  182. badgeDelegate: DefaultBadgeDelegate(),
  183. pickType: pickType,
  184. );
  185. assert(provider != null, "provider must be not null");
  186. assert(context != null, "context must be not null");
  187. assert(pickType != null, "pickType must be not null");
  188. return ChangeNotifierProvider(
  189. create: (_) => PhotoProvider(
  190. provider: provider,
  191. options: options,
  192. pickedAssetList: pickedAssetList,
  193. ),
  194. child: PhotoListPage(
  195. onSelected: onSelected,
  196. options: options,
  197. isFullImage: isFullImage,
  198. ),
  199. );
  200. }
  201. Future<void> requestPermission(BuildContext context,
  202. {@required I18nProvider provider}) async {
  203. var requestPermission = await PhotoManager.requestPermission();
  204. if (requestPermission != true) {
  205. var result = await showDialog(
  206. context: context,
  207. builder: (ctx) => NotPermissionDialog(
  208. provider.getNotPermissionText(),
  209. ),
  210. );
  211. if (result == true) {
  212. PhotoManager.openSetting();
  213. }
  214. return null;
  215. }
  216. }
  217. Future<PickedEntity> _openGalleryContentPage(
  218. BuildContext context,
  219. Options options,
  220. I18nProvider provider,
  221. List<AssetPathEntity> photoList,
  222. List<AssetEntity> pickedAssetList,
  223. ) async {
  224. return Navigator.of(context, rootNavigator: true).push(
  225. MaterialPageRoute(
  226. builder: (ctx) => ChangeNotifierProvider(
  227. create: (_) => PhotoProvider(
  228. provider: provider,
  229. options: options,
  230. pickedAssetList: pickedAssetList,
  231. ),
  232. child: PhotoMainPage(
  233. onClose: (PickedEntity value) {
  234. Navigator.pop(ctx, value);
  235. },
  236. options: options,
  237. photoList: photoList,
  238. ),
  239. ),
  240. ),
  241. );
  242. }
  243. }