No Description

photo.dart 8.2KB

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