Procházet zdrojové kódy

修改了lru cache

现在的lru cache和图片尺寸相关联

初始化时的loading

排序的delegate
cjl_macbook před 6 roky
rodič
revize
132c645760

+ 8
- 0
CHANGELOG.md Zobrazit soubor

1
 # CHANGELOG
1
 # CHANGELOG
2
 
2
 
3
+## [0.0.5] add a params
4
+
5
+add the sort delegate to help user sort gallery
6
+
7
+Optimized LruCache
8
+
9
+add a loading refresh indicator in the gallery
10
+
3
 ## [0.0.4] fix #1
11
 ## [0.0.4] fix #1
4
 
12
 
5
 fix request other permission will crash bug
13
 fix request other permission will crash bug

+ 38
- 21
README.md Zobrazit soubor

13
 
13
 
14
 ```yaml
14
 ```yaml
15
 dependencies:
15
 dependencies:
16
-  photo: ^0.0.4
16
+  photo: ^0.0.5
17
 ```
17
 ```
18
 
18
 
19
 ## import
19
 ## import
26
 ## use
26
 ## use
27
 
27
 
28
 ```dart
28
 ```dart
29
-  void _pickImage(BuildContext context) async {
30
-    List<ImageEntity> imgList = await PhotoPicker.pickImage(
31
-      context: context, // BuildContext requied
32
-
33
-      /// The following are optional parameters.
34
-      themeColor: Colors.green, // the title color and bottom color
35
-      padding: 5.0, // item padding
36
-      dividerColor: Colors.deepOrange, // divider color
37
-      disableColor: Colors.grey.shade300, // the check box disable color
38
-      itemRadio: 0.88, // the content item radio
39
-      maxSelected: 8, // max picker image count
40
-      provider: CNProvider(), // i18n provider ,default is chinese. , you can custom I18nProvider or use ENProvider()
41
-      rowCount: 5,  // item row count
42
-      textColor: Colors.white, // text color
43
-      thumbSize: 150, // preview thumb size, optional, default is 64
44
-    );
45
-
46
-    imgList.forEach((e) async {
47
-      print(e.id);
48
-    });
29
+  void _pickImage() async {
30
+      List<ImageEntity> imgList = await PhotoPicker.pickImage(
31
+        context: context, // BuildContext requied
32
+
33
+        /// The following are optional parameters.
34
+        themeColor: Colors.green, // the title color and bottom color
35
+        padding: 5.0, // item padding
36
+        dividerColor: Colors.deepOrange, // divider color
37
+        disableColor: Colors.grey.shade300, // the check box disable color
38
+        itemRadio: 0.88, // the content item radio
39
+        maxSelected: 8, // max picker image count
40
+        provider: CNProvider(), // i18n provider ,default is chinese. , you can custom I18nProvider or use ENProvider()
41
+        rowCount: 5,  // item row count
42
+        textColor: Colors.white, // text color
43
+        thumbSize: 150, // preview thumb size , default is 64
44
+        sortDelegate: SortDelegate.common, // default is common ,or you make custom delegate
45
+      );
46
+
47
+      imgList.forEach((e) async {
48
+          print(e.id);
49
+      });
49
   }
50
   }
50
 ```
51
 ```
51
 
52
 
77
 if you use the proguard
78
 if you use the proguard
78
 
79
 
79
 see the [github](https://github.com/bumptech/glide#proguard)
80
 see the [github](https://github.com/bumptech/glide#proguard)
81
+
82
+
83
+## about ios
84
+
85
+Because the album is a privacy privilege, you need user permission to access it. You must to modify the `Info.plist` file in Runner project.
86
+
87
+
88
+like next
89
+
90
+```plist
91
+	<key>NSPhotoLibraryUsageDescription</key>
92
+    <string>App需要您的同意,才能访问相册</string>
93
+```
94
+
95
+xcode like image
96
+![in xcode](https://github.com/CaiJingLong/some_asset/blob/master/flutter_photo2.png)

+ 27
- 20
example/lib/main.dart Zobrazit soubor

31
 
31
 
32
   void _pickImage() async {
32
   void _pickImage() async {
33
     List<ImageEntity> imgList = await PhotoPicker.pickImage(
33
     List<ImageEntity> imgList = await PhotoPicker.pickImage(
34
-      context: context,
35
-      themeColor: Colors.green,
36
-      padding: 5.0,
37
-      dividerColor: Colors.deepOrange,
38
-      disableColor: Colors.grey.shade300,
39
-      itemRadio: 0.88,
40
-      maxSelected: 8,
41
-      provider: CNProvider(),
42
-      rowCount: 5,
43
-      textColor: Colors.white,
44
-      thumbSize: 250,
45
-    );
34
+      context: context, // BuildContext requied
46
 
35
 
47
-    List<String> r = [];
36
+      /// The following are optional parameters.
37
+      themeColor: Colors.green, // the title color and bottom color
38
+      padding: 5.0, // item padding
39
+      dividerColor: Colors.deepOrange, // divider color
40
+      disableColor: Colors.grey.shade300, // the check box disable color
41
+      itemRadio: 0.88, // the content item radio
42
+      maxSelected: 8, // max picker image count
43
+      provider: CNProvider(), // i18n provider ,default is chinese. , you can custom I18nProvider or use ENProvider()
44
+      rowCount: 5,  // item row count
45
+      textColor: Colors.white, // text color
46
+      thumbSize: 150, // preview thumb size , default is 64
47
+      sortDelegate: SortDelegate.common, // default is common ,or you make custom delegate to sort your gallery
48
+    );
48
 
49
 
49
-    for(var e in imgList){
50
-      var file = await e.file;
51
-      r.add(file.absolute.path);
50
+    if (imgList == null) {
51
+      currentSelected = "not select item";
52
+    } else {
53
+      List<String> r = [];
54
+      for (var e in imgList) {
55
+        var file = await e.file;
56
+        r.add(file.absolute.path);
57
+      }
58
+      currentSelected = r.join("\n\n");
52
     }
59
     }
53
-
54
-    currentSelected = r.join("\n\n");
55
-
56
     setState(() {});
60
     setState(() {});
57
   }
61
   }
58
 
62
 
64
       ),
68
       ),
65
       body: Container(
69
       body: Container(
66
         child: Center(
70
         child: Center(
67
-          child: Text('$currentSelected'),
71
+          child: Text(
72
+            '$currentSelected',
73
+            textAlign: TextAlign.center,
74
+          ),
68
         ),
75
         ),
69
       ),
76
       ),
70
       floatingActionButton: new FloatingActionButton(
77
       floatingActionButton: new FloatingActionButton(

+ 19
- 7
lib/photo.dart Zobrazit soubor

3
 import 'dart:async';
3
 import 'dart:async';
4
 
4
 
5
 import 'package:flutter/material.dart';
5
 import 'package:flutter/material.dart';
6
+import 'package:photo_manager/photo_manager.dart';
7
+
6
 import 'package:photo/src/entity/options.dart';
8
 import 'package:photo/src/entity/options.dart';
7
 import 'package:photo/src/provider/i18n_provider.dart';
9
 import 'package:photo/src/provider/i18n_provider.dart';
8
 import 'package:photo/src/ui/dialog/not_permission_dialog.dart';
10
 import 'package:photo/src/ui/dialog/not_permission_dialog.dart';
9
 import 'package:photo/src/ui/photo_app.dart';
11
 import 'package:photo/src/ui/photo_app.dart';
10
-import 'package:photo_manager/photo_manager.dart';
12
+import 'package:photo/src/delegate/sort_delegate.dart';
11
 
13
 
12
-export 'package:photo/src/provider/i18n_provider.dart' show I18NCustomProvider,I18nProvider,CNProvider,ENProvider;
14
+export 'package:photo/src/provider/i18n_provider.dart'
15
+    show I18NCustomProvider, I18nProvider, CNProvider, ENProvider;
16
+export 'package:photo/src/delegate/sort_delegate.dart';
13
 
17
 
14
 class PhotoPicker {
18
 class PhotoPicker {
15
   static PhotoPicker _instance;
19
   static PhotoPicker _instance;
53
     Color disableColor,
57
     Color disableColor,
54
     int thumbSize = 64,
58
     int thumbSize = 64,
55
     I18nProvider provider = I18nProvider.chinese,
59
     I18nProvider provider = I18nProvider.chinese,
60
+    SortDelegate sortDelegate,
56
   }) {
61
   }) {
57
     assert(provider != null, "provider must be not null");
62
     assert(provider != null, "provider must be not null");
58
     assert(context != null, "context must be not null");
63
     assert(context != null, "context must be not null");
62
     disableColor ??= Theme.of(context)?.disabledColor ?? Colors.grey;
67
     disableColor ??= Theme.of(context)?.disabledColor ?? Colors.grey;
63
     textColor ??= Colors.white;
68
     textColor ??= Colors.white;
64
 
69
 
70
+    sortDelegate ??= SortDelegate.common;
71
+
65
     var options = Options(
72
     var options = Options(
66
       rowCount: rowCount,
73
       rowCount: rowCount,
67
       dividerColor: dividerColor,
74
       dividerColor: dividerColor,
72
       textColor: textColor,
79
       textColor: textColor,
73
       themeColor: themeColor,
80
       themeColor: themeColor,
74
       thumbSize: thumbSize,
81
       thumbSize: thumbSize,
82
+      sortDelegate: sortDelegate,
75
     );
83
     );
76
 
84
 
77
-    return PhotoPicker()._pickImage(context, options, provider);
85
+    return PhotoPicker()._pickImage(
86
+      context,
87
+      options,
88
+      provider,
89
+    );
78
   }
90
   }
79
 
91
 
80
   Future<List<ImageEntity>> _pickImage(
92
   Future<List<ImageEntity>> _pickImage(
100
   }
112
   }
101
 
113
 
102
   Future<List<ImageEntity>> _openGalleryContentPage(
114
   Future<List<ImageEntity>> _openGalleryContentPage(
103
-      BuildContext context, Options options, I18nProvider provider)async{
115
+      BuildContext context, Options options, I18nProvider provider) async {
104
     return Navigator.of(context).push(
116
     return Navigator.of(context).push(
105
       MaterialPageRoute(
117
       MaterialPageRoute(
106
         builder: (ctx) => PhotoApp(
118
         builder: (ctx) => PhotoApp(
107
-          options: options,
108
-          provider: provider,
109
-        ),
119
+              options: options,
120
+              provider: provider,
121
+            ),
110
       ),
122
       ),
111
     );
123
     );
112
   }
124
   }

+ 66
- 0
lib/src/delegate/sort_delegate.dart Zobrazit soubor

1
+import 'package:photo_manager/photo_manager.dart';
2
+
3
+abstract class SortDelegate {
4
+  const SortDelegate();
5
+
6
+  void sort(List<ImagePathEntity> list);
7
+
8
+  static const none = DefaultSortDelegate();
9
+
10
+  static const common = CommonSortDelegate();
11
+}
12
+
13
+class DefaultSortDelegate extends SortDelegate {
14
+  const DefaultSortDelegate();
15
+
16
+  @override
17
+  void sort(List<ImagePathEntity> list) {}
18
+}
19
+
20
+class CommonSortDelegate extends SortDelegate {
21
+  const CommonSortDelegate();
22
+
23
+  @override
24
+  void sort(List<ImagePathEntity> list) {
25
+    list.sort((path1, path2) {
26
+      if (path1 == ImagePathEntity.all) {
27
+        return -1;
28
+      }
29
+
30
+      if (path2 == ImagePathEntity.all) {
31
+        return 1;
32
+      }
33
+
34
+      if (_isCamera(path1)) {
35
+        return -1;
36
+      }
37
+
38
+      if (_isCamera(path2)) {
39
+        return 1;
40
+      }
41
+
42
+      if (_isScreenShot(path1)) {
43
+        return -1;
44
+      }
45
+
46
+      if (_isScreenShot(path2)) {
47
+        return 1;
48
+      }
49
+
50
+      return otherSort(path1, path2);
51
+    });
52
+  }
53
+
54
+  int otherSort(ImagePathEntity path1, ImagePathEntity path2) {
55
+    return path1.name.compareTo(path2.name);
56
+  }
57
+
58
+  bool _isCamera(ImagePathEntity entity) {
59
+    return entity.name.toUpperCase() == "camera".toUpperCase();
60
+  }
61
+
62
+  bool _isScreenShot(ImagePathEntity entity) {
63
+    return entity.name.toUpperCase() == "screenshots".toUpperCase() ||
64
+        entity.name.toUpperCase() == "screenshot".toUpperCase();
65
+  }
66
+}

+ 23
- 5
lib/src/engine/lru_cache.dart Zobrazit soubor

4
 import 'package:photo_manager/photo_manager.dart';
4
 import 'package:photo_manager/photo_manager.dart';
5
 
5
 
6
 class ImageLruCache {
6
 class ImageLruCache {
7
-  static LRUMap<ImageEntity, Uint8List> _map = LRUMap(500);
7
+  static LRUMap<_ImageCacheEntity, Uint8List> _map = LRUMap(500);
8
 
8
 
9
-  static Uint8List getData(ImageEntity entity) {
10
-    return _map.get(entity);
9
+  static Uint8List getData(ImageEntity entity, [int size = 64]) {
10
+    return _map.get(_ImageCacheEntity(entity, size));
11
   }
11
   }
12
 
12
 
13
-  static void setData(ImageEntity entity, Uint8List list) {
14
-    _map.put(entity, list);
13
+  static void setData(ImageEntity entity, int size, Uint8List list) {
14
+    _map.put(_ImageCacheEntity(entity,size), list);
15
   }
15
   }
16
 }
16
 }
17
 
17
 
18
+class _ImageCacheEntity {
19
+  ImageEntity entity;
20
+  int size;
21
+
22
+  _ImageCacheEntity(this.entity, this.size);
23
+
24
+  @override
25
+  bool operator ==(Object other) =>
26
+      identical(this, other) ||
27
+      other is _ImageCacheEntity &&
28
+          runtimeType == other.runtimeType &&
29
+          entity == other.entity &&
30
+          size == other.size;
31
+
32
+  @override
33
+  int get hashCode => entity.hashCode ^ size.hashCode;
34
+}
35
+
18
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
36
 // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
19
 // for details. All rights reserved. Use of this source code is governed by a
37
 // for details. All rights reserved. Use of this source code is governed by a
20
 // BSD-style license that can be found in the LICENSE file.
38
 // BSD-style license that can be found in the LICENSE file.

+ 4
- 0
lib/src/entity/options.dart Zobrazit soubor

1
 import 'package:flutter/material.dart';
1
 import 'package:flutter/material.dart';
2
+import 'package:photo/src/delegate/sort_delegate.dart';
2
 
3
 
3
 class Options {
4
 class Options {
4
   final int rowCount;
5
   final int rowCount;
19
 
20
 
20
   final int thumbSize;
21
   final int thumbSize;
21
 
22
 
23
+  final SortDelegate sortDelegate;
24
+
22
   const Options({
25
   const Options({
23
     this.rowCount,
26
     this.rowCount,
24
     this.maxSelected,
27
     this.maxSelected,
29
     this.textColor,
32
     this.textColor,
30
     this.disableColor,
33
     this.disableColor,
31
     this.thumbSize,
34
     this.thumbSize,
35
+    this.sortDelegate,
32
   });
36
   });
33
 }
37
 }

+ 9
- 0
lib/src/provider/i18n_provider.dart Zobrazit soubor

16
 
16
 
17
   String getAllGalleryText(Options options);
17
   String getAllGalleryText(Options options);
18
 
18
 
19
+  String loadingText(){
20
+    return "loading...";
21
+  }
22
+
19
   I18NPermissionProvider getNotPermissionText(Options options);
23
   I18NPermissionProvider getNotPermissionText(Options options);
20
 
24
 
21
   static const I18nProvider chinese = CNProvider();
25
   static const I18nProvider chinese = CNProvider();
56
     return "全部图片";
60
     return "全部图片";
57
   }
61
   }
58
 
62
 
63
+  @override
64
+  String loadingText() {
65
+    return "加载中...";
66
+  }
67
+
59
   @override
68
   @override
60
   I18NPermissionProvider getNotPermissionText(Options options) {
69
   I18NPermissionProvider getNotPermissionText(Options options) {
61
     return I18NPermissionProvider(
70
     return I18NPermissionProvider(

+ 42
- 3
lib/src/ui/page/photo_main_page.dart Zobrazit soubor

35
 
35
 
36
   ImagePathEntity _currentPath = ImagePathEntity.all;
36
   ImagePathEntity _currentPath = ImagePathEntity.all;
37
 
37
 
38
+  bool _isInit = false;
39
+
38
   ImagePathEntity get currentPath {
40
   ImagePathEntity get currentPath {
39
     if (_currentPath == null) {
41
     if (_currentPath == null) {
40
       return null;
42
       return null;
150
 
152
 
151
   void _refreshList() async {
153
   void _refreshList() async {
152
     var pathList = await PhotoManager.getImagePathList();
154
     var pathList = await PhotoManager.getImagePathList();
155
+
156
+    options.sortDelegate.sort(pathList);
157
+
153
     galleryPathList.clear();
158
     galleryPathList.clear();
154
     galleryPathList.addAll(pathList);
159
     galleryPathList.addAll(pathList);
155
 
160
 
156
     var imageList = await currentPath.imageList;
161
     var imageList = await currentPath.imageList;
157
     this.list.clear();
162
     this.list.clear();
158
     this.list.addAll(imageList);
163
     this.list.addAll(imageList);
159
-    setState(() {});
164
+    setState(() {
165
+      _isInit = true;
166
+    });
160
   }
167
   }
161
 
168
 
162
   Widget _buildBody() {
169
   Widget _buildBody() {
170
+    if (!_isInit) {
171
+      return _buildLoading();
172
+    }
173
+
163
     return Container(
174
     return Container(
164
       color: options.disableColor,
175
       color: options.disableColor,
165
       child: GridView.builder(
176
       child: GridView.builder(
341
     }
352
     }
342
     return false;
353
     return false;
343
   }
354
   }
355
+
356
+  Widget _buildLoading() {
357
+    return Center(
358
+      child: Column(
359
+        children: <Widget>[
360
+          Container(
361
+            width: 40.0,
362
+            height: 40.0,
363
+            padding: const EdgeInsets.all(5.0),
364
+            child: CircularProgressIndicator(
365
+              valueColor: AlwaysStoppedAnimation(themeColor),
366
+            ),
367
+          ),
368
+          Padding(
369
+            padding: const EdgeInsets.all(8.0),
370
+            child: Text(
371
+              i18nProvider.loadingText(),
372
+              style: const TextStyle(
373
+                fontSize: 12.0,
374
+              ),
375
+            ),
376
+          ),
377
+        ],
378
+        crossAxisAlignment: CrossAxisAlignment.center,
379
+        mainAxisAlignment: MainAxisAlignment.center,
380
+      ),
381
+    );
382
+  }
344
 }
383
 }
345
 
384
 
346
 class _BottomWidget extends StatefulWidget {
385
 class _BottomWidget extends StatefulWidget {
457
 
496
 
458
   @override
497
   @override
459
   Widget build(BuildContext context) {
498
   Widget build(BuildContext context) {
460
-    var thumb = ImageLruCache.getData(entity);
499
+    var thumb = ImageLruCache.getData(entity, size);
461
     if (thumb != null) {
500
     if (thumb != null) {
462
       return _buildImageItem(thumb);
501
       return _buildImageItem(thumb);
463
     }
502
     }
468
         var futureData = snapshot.data;
507
         var futureData = snapshot.data;
469
         if (snapshot.connectionState == ConnectionState.done &&
508
         if (snapshot.connectionState == ConnectionState.done &&
470
             futureData != null) {
509
             futureData != null) {
471
-          ImageLruCache.setData(entity, futureData);
510
+          ImageLruCache.setData(entity, size, futureData);
472
           return _buildImageItem(futureData);
511
           return _buildImageItem(futureData);
473
         }
512
         }
474
         return Center(
513
         return Center(

+ 1
- 1
pubspec.yaml Zobrazit soubor

1
 name: photo
1
 name: photo
2
 description: image picker, multi picker,use flutter as ui, if you want to build custom ui,you just use photo_manager.
2
 description: image picker, multi picker,use flutter as ui, if you want to build custom ui,you just use photo_manager.
3
-version: 0.0.4
3
+version: 0.0.5
4
 author: caijinglong<cjl_spy@163.com>
4
 author: caijinglong<cjl_spy@163.com>
5
 homepage: https://github.com/CaiJingLong/flutter_photo
5
 homepage: https://github.com/CaiJingLong/flutter_photo
6
 
6