1
- # Flutter 仿微信资源选择器
1
+ # Flutter WeChat Assets Picker
2
2
3
3
[ ![ pub package] ( https://img.shields.io/pub/v/wechat_assets_picker?color=42a012&label=%E7%A8%B3%E5%AE%9A%E7%89%88&logo=dart&style=flat-square )] ( https://pub.flutter-io.cn/packages/wechat_assets_picker )
4
4
[ ![ pub package] ( https://img.shields.io/pub/v/wechat_assets_picker?color=42a012&include_prereleases&label=%E5%BC%80%E5%8F%91%E7%89%88&logo=dart&style=flat-square )] ( https://pub.flutter-io.cn/packages/wechat_assets_picker )
13
13
14
14
Language: [ English] ( README.md ) | 中文简体
15
15
16
- 对标微信的** 资源选择器** ,基于` photo_manager ` 实现资源相关功能,` extended_image ` 用于查看图片,` provider ` 用于协助管理选择器的状态。
16
+ 基于微信 UI 的 ** 资源选择器** ,基于 ` photo_manager ` 实现资源相关功能,
17
+ ` extended_image ` 用于查看图片,` provider ` 用于协助管理选择器的状态。
17
18
18
- 拍照及录制视频,请查看 example 详细用法,并前往 [ wechat_camera_picker] ( https://fluttercandies.github.io/flutter_wechat_camera_picker/README-ZH.html ) 。
19
+ 需要拍照及录制视频,请查看示例的详细用法,
20
+ 并前往 [ wechat_camera_picker] ( https://fluttercandies.github.io/flutter_wechat_camera_picker/README-ZH.html ) 。
19
21
20
- 所有的界面细节基于 微信 7 .x 版本,将在微信版本更新后随时进行跟进。
22
+ 所有的界面细节基于 ** 微信 8 .x 版本** ,将在微信版本更新后随时进行跟进。
21
23
22
- ** 贴士 :** 如果你觉得你的自定义实现会在某些程度上帮助其他人实现他们的需求,你可以通过 PR 提交你的实现 。
24
+ ** 注意 :** 如果你觉得你的自定义实现会在某些程度上帮助其他人实现他们的需求,你可以通过 PR 提交你的自定义实现 。
23
25
更多信息请参考 [ 贡献自定义实现] ( example/lib/customs/CONTRIBUTING.md ) 。
24
26
25
27
## 目录 🗂
@@ -32,15 +34,14 @@ Language: [English](README.md) | 中文简体
32
34
* [ Flutter] ( #flutter )
33
35
* [ Android] ( #android )
34
36
* [ iOS] ( #ios )
35
- * [ MacOS ] ( #macos )
37
+ * [ macOS ] ( #macos )
36
38
* [ 使用方法] ( #使用方法- )
37
39
* [ 简单的使用方法] ( #简单的使用方法 )
40
+ * [ 使用自定义代理] ( #使用自定义代理 )
38
41
* [ 完整参数的使用方法] ( #完整参数的使用方法 )
39
42
* [ 展示选中的资源] ( #展示选中的资源 )
40
43
* [ 注册资源变化回调] ( #注册资源变化回调 )
41
44
* [ 自定义类型或 UI] ( #自定义类型或-ui )
42
- * [ 类介绍] ( #类介绍- )
43
- * [ ` AssetEntity ` ] ( #assetentity )
44
45
* [ 常见问题] ( #常见问题- )
45
46
* [ 编译时报错 ` Unresolved reference: R ` ] ( #编译时报错-unresolved-reference-r )
46
47
* [ 如何获取资源的路径以进行上传或编辑等操作的整合?] ( #如何获取资源的路径以进行上传或编辑等操作的整合 )
@@ -81,15 +82,18 @@ Language: [English](README.md) | 中文简体
81
82
82
83
## 开始前的注意事项 ‼️
83
84
84
- 尽管该库提供了资源的选择,其仍然要求使用者构建自己的方法来处理显示、上传等操作。如果你在使用该库的过程对某些方法或API有疑问,请运行demo并查看[ photo_manager] ( https://github.com/CaiJingLong/flutter_photo_manager ) 对相关方法的使用说明。
85
+ 尽管该库提供了资源的选择,其仍然要求使用者构建自己的方法来处理显示、上传等操作。
86
+ 如果你在使用该库的过程对某些方法或API有疑问,
87
+ 请运行示例并查看 [ photo_manager] ( https://github.com/CaiJingLong/flutter_photo_manager ) 对相关方法的使用说明。
85
88
86
89
## 准备工作 🍭
87
90
88
91
### 版本限制
89
92
90
93
Flutter SDK:` >=2.0.0 ` 。
91
94
92
- 如果在 ` flutter pub get ` 时遇到了失败问题,请使用 ` dependency_overrides ` 解决。参考[ 这里] ( #xxx-版本获取冲突-例如-dartx ) 。
95
+ 如果在 ` flutter pub get ` 时遇到了失败问题,请使用 ` dependency_overrides ` 解决。
96
+ 参考 [ 版本获取冲突] ( #xxx-版本获取冲突-例如-dartx ) 。
93
97
94
98
### Flutter
95
99
@@ -100,9 +104,11 @@ dependencies:
100
104
wechat_assets_picker : ^latest_version
101
105
` ` `
102
106
103
- 最新的**稳定**版本是: [](https://pub.flutter-io.cn/packages/wechat_assets_picker)
107
+ 最新的 **稳定** 版本是:
108
+ [](https://pub.flutter-io.cn/packages/wechat_assets_picker)
104
109
105
- 最新的**开发**版本是: [](https://pub.flutter-io.cn/packages/wechat_assets_picker)
110
+ 最新的 **开发** 版本是:
111
+ [](https://pub.flutter-io.cn/packages/wechat_assets_picker)
106
112
107
113
在你的代码中导入:
108
114
@@ -112,22 +118,25 @@ import 'package:wechat_assets_picker/wechat_assets_picker.dart';
112
118
113
119
### Android
114
120
115
- 依赖要求项目的安卓原生部分整合至 Android embedding v2,更多信息请至 [ Upgrading pre 1.12 Android projects] ( https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects ) 查看。
121
+ 依赖要求项目的安卓原生部分整合至 Android embedding v2,
122
+ 更多信息请至 [ Upgrading pre 1.12 Android projects] ( https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects )
123
+ 查看。
116
124
117
125
需要声明的权限:` INTERNET ` , ` READ_EXTERNAL_STORAGE ` , ` WRITE_EXTERNAL_STORAGE ` , ` ACCESS_MEDIA_LOCATION ` 。
126
+ 如果你不需要 ` ACCESS_MEDIA_LOCATION ` 权限,请参考 [ 禁用媒体位置权限] ( #禁用媒体位置权限 ) 要进行移除。
118
127
119
- 如果你发现有一些与` Glide ` 有关的警告日志输出,那么主项目就需要实现 ` AppGlideModule ` 。请查看 [ Generated API] ( https://muyangmin.github.io/glide-docs-cn/doc/generatedapi.html ) .
128
+ 如果你发现有一些与 ` Glide ` 有关的警告日志输出,那么主项目就需要实现 ` AppGlideModule ` 。
129
+ 请查看 [ Generated API] ( https://muyangmin.github.io/glide-docs-cn/doc/generatedapi.html ) .
120
130
121
131
### iOS
122
132
123
133
在 ` ios/Podfile ` 中指定最低构建版本至 ** 9.0** 。
124
- ```
134
+ ``` ruby
125
135
platform :ios , ' 9.0'
126
136
```
127
137
128
- 将以下内容添加至` info.plist ` 。
129
-
130
- ```
138
+ 将以下内容添加至 ` info.plist ` 。
139
+ ``` plist
131
140
<key>NSAppTransportSecurity</key>
132
141
<dict>
133
142
<key>NSAllowsArbitraryLoads</key>
@@ -137,7 +146,7 @@ platform :ios, '9.0'
137
146
<string>你的相册权限描述</string>
138
147
```
139
148
140
- ### MacOS
149
+ ### macOS
141
150
142
151
目前 Flutter 桌面版仍然在开发阶段,所以请注意,任何与桌面版本有关的问题都不会受到技术支持。
143
152
@@ -149,7 +158,7 @@ platform :ios, '9.0'
149
158
150
159
4 . ![ step 2] ( https://tva1.sinaimg.cn/large/007S8ZIlgy1ghw67vd3f2j30jv04zgm5.jpg )
151
160
152
- 5 . 与 iOS 一样,添加相同的东西到 ` info.plist ` 里。
161
+ 5 . 与 iOS 一样,添加相同的东西到 ` info.plist ` 里。
153
162
154
163
## 使用方法 📖
155
164
@@ -171,6 +180,7 @@ platform :ios, '9.0'
171
180
| filterOptions | ` FilterOptionGroup? ` | 允许用户自定义资源过滤条件 | ` null ` |
172
181
| specialItemBuilder | ` WidgetBuilder? ` | 自定义item的构造方法 | ` null ` |
173
182
| specialItemPosition | ` SpecialItemPosition ` | 允许用户在选择器中添加一个自定义item,并指定位置。 | ` SpecialPosition.none ` |
183
+ | loadingIndicatorBuilder | ` IndicatorBuilder? ` | 加载器的实现 | ` null ` |
174
184
| allowSpecialItemWhenEmpty | ` bool ` | 在资源为空时是否允许显示自定义item | ` false ` |
175
185
| routeCurve | ` Curve ` | 选择构造路由动画的曲线 | ` Curves.easeIn ` |
176
186
| routeDuration | ` Duration ` | 选择构造路由动画的时间 | ` const Duration(milliseconds: 500) ` |
@@ -181,12 +191,16 @@ platform :ios, '9.0'
181
191
final List<AssetEntity> assets = await AssetPicker.pickAssets(context);
182
192
```
183
193
184
- 或者
194
+ ### 使用自定义代理
185
195
186
196
``` dart
187
- AssetPicker.pickAsset(context).then((List<AssetEntity> assets) {
188
- /.../
189
- });
197
+ final YourAssetPickerProvider provider = your_provider;
198
+ final CustomAssetPickerBuilderDelegate builder = your_builder(provider);
199
+ final List<YourAssetEntity>? result = await AssetPicker.pickAssetsWithDelegate(
200
+ context,
201
+ provider: provider,
202
+ delegate: builder,
203
+ );
190
204
```
191
205
192
206
### 完整参数的使用方法
@@ -195,7 +209,8 @@ AssetPicker.pickAsset(context).then((List<AssetEntity> assets) {
195
209
196
210
### 展示选中的资源
197
211
198
- ` AssetEntityImageProvider ` 可以为 ** 图片 & 视频** 展示缩略图,以及展示 ** 图片的原图** 。它的使用方法与常见的 ` ImageProvider ` 一致。
212
+ ` AssetEntityImageProvider ` 可以为 ** 图片 & 视频** 展示缩略图,以及展示 ** 图片的原图** 。
213
+ 它的使用方法与常见的 ` ImageProvider ` 一致。
199
214
200
215
``` dart
201
216
Image(image: AssetEntityImageProvider(asset, isOriginal: false))
@@ -208,6 +223,7 @@ Image(image: AssetEntityImageProvider(asset, isOriginal: false))
208
223
``` dart
209
224
AssetPicker.registerObserve(); // 注册回调
210
225
```
226
+
211
227
``` dart
212
228
AssetPicker.unregisterObserve(); // 取消注册回调
213
229
```
@@ -219,94 +235,6 @@ AssetPicker.unregisterObserve(); // 取消注册回调
219
235
配合继承与重载,实现对应抽象类和类中的方法。更多用法请查看示例中的 ` Custom ` 页面,该页面包含一个以
220
236
` <File, Directory> ` 为类型基础的选择器。
221
237
222
- ## 类介绍 💭
223
-
224
- ### ` AssetEntity `
225
-
226
- ``` dart
227
- /// Android: Database _id column
228
- /// iOS : `PhotoKit > PHObject > localIdentifier`
229
- String id;
230
-
231
- /// Android: `MediaStore.MediaColumns.DISPLAY_NAME`
232
- /// iOS : `PHAssetResource.filename`. Nullable
233
- /// If you must need it, See [FilterOption.needTitle] or use [titleAsync].
234
- String title;
235
-
236
- /// Android: title
237
- /// iOS : [PHAsset valueForKey:@"filename"]
238
- Future<String> get titleAsync;
239
-
240
- /// * 1: [AssetType.image]
241
- /// * 2: [AssetType.video]
242
- /// * 3: [AssetType.audio]
243
- /// * default: [AssetType.other]
244
- AssetType get type;
245
-
246
- /// Asset type int value.
247
- int typeInt;
248
-
249
- /// Duration of video, the unit is second.
250
- /// If [type] is [AssetType.image], then it's value is 0.
251
- /// See also: [videoDuration].
252
- int duration;
253
-
254
- /// Width of the asset.
255
- int width;
256
-
257
- /// Height of the asset.
258
- int height;
259
-
260
- /// Location information when shooting. Nullable.
261
- /// When the device is Android 10 or above, it's ALWAYS null.
262
- /// See also: [longitude].
263
- double get latitude => _latitude ?? 0;
264
- /// Also with a setter.
265
-
266
- /// Get lat/lng from `MediaStore`(Android) / `Photos`(iOS).
267
- /// In Android Q, this comes from EXIF.
268
- Future<LatLng> latlngAsync();
269
-
270
- /// Get [File] object.
271
- /// Notice that this is not the origin file, so when it comes to some
272
- /// scene like reading a GIF's file, please use `originFile`, or you'll
273
- /// get a JPG.
274
- Future<File> get file async;
275
-
276
- /// Get the original [File] object.
277
- Future<File> get originFile async;
278
-
279
- /// The raw data for the entity, it may be large.
280
- /// This property is NOT RECOMMENDED for video assets.
281
- Future<Uint8List> get originBytes;
282
-
283
- /// The thumbnail data for the entity. Usually use for displaying a thumbnail image widget.
284
- Future<Uint8List> get thumbData;
285
-
286
- /// Get thumbnail data with specific size.
287
- Future<Uint8List> thumbDataWithSize(
288
- int width,
289
- int height, {
290
- ThumbFormat format = ThumbFormat.jpeg,
291
- int quality = 100,
292
- });
293
-
294
- /// Get the asset's size. Nullable if the manager is null,
295
- Size get size;
296
-
297
- /// If the asset is deleted, return false.
298
- Future<bool> get exists => PhotoManager._assetExistsWithId(id);
299
-
300
- /// The url is provided to some video player. Such as [flutter_ijkplayer](https://pub.dev/packages/flutter_ijkplayer)
301
- ///
302
- /// Android: `content://media/external/video/media/894857`
303
- /// iOS : `file:///var/mobile/Media/DCIM/118APPLE/IMG_8371.MOV` in iOS.
304
- Future<String> getMediaUrl();
305
-
306
- /// Refresh the properties for the entity.
307
- Future<AssetEntity> refreshProperties() async;
308
- ```
309
-
310
238
## 常见问题 ❔
311
239
312
240
### 编译时报错 ` Unresolved reference: R `
@@ -333,7 +261,10 @@ FAILURE: Build failed with an exception.
333
261
334
262
### 如何更改 'Recent' 或其他路径的名称或属性?
335
263
336
- 由 ` photo_manager ` 传递的 “Recent” 路径,包含了您设备上的所有的 ` AssetEntity ` 。大部分的平台都会将这个路径命名为 “Recent”。尽管我们提供了自定义文字构建的能力,但是 ` AssetPathEntity ` 的名字或属性只能通过 ` SortPathDelegate ` 进行更改。这是你能访问到所有 ` AssetPathEntity ` 的唯一方法,或者说,是现阶段我们暴露出来的唯一方法。
264
+ 由 ` photo_manager ` 传递的 “Recent” 路径,包含了你设备上的所有的 ` AssetEntity ` 。
265
+ 大部分的平台都会将这个路径命名为 “Recent”。尽管我们提供了自定义文字构建的能力,
266
+ 但是 ` AssetPathEntity ` 的名字或属性只能通过 ` SortPathDelegate ` 进行更改。
267
+ 这是你能访问到所有 ` AssetPathEntity ` 的唯一方法,或者说,是现阶段我们暴露出来的唯一方法。
337
268
338
269
若需要更改某一个路径的名字,继承 ` SortPathDelegate ` 并实现你自己的构建,接着像如下代码一样进行编写:
339
270
@@ -365,12 +296,12 @@ class CustomSortPathDelegate extends SortPathDelegate {
365
296
366
297
### 从 ` File ` 或 ` Uint8List ` 创建 ` AssetEntity ` 的方法
367
298
368
- 如果需要使用此库结合一些拍照需求,可通过以下方法将` File ` 或 ` Uint8List ` 转为 ` AssetEntity ` 。
299
+ 如果需要使用此库结合一些拍照需求,可通过以下方法将 ` File ` 或 ` Uint8List ` 转为 ` AssetEntity ` 。
369
300
370
301
``` dart
371
- final File file = your_file; // 你的File对象
372
- final Uint8List byteData = await file.readAsBytes(); // 转为Uint8List
373
- final AssetEntity imageEntity = await PhotoManager.editor.saveImage(byteData); // 存入手机并生成AssetEntity
302
+ final File file = your_file; // 你的 File 对象
303
+ final Uint8List byteData = await file.readAsBytes(); // 转为 Uint8List
304
+ final AssetEntity imageEntity = await PhotoManager.editor.saveImage(byteData); // 存入手机并生成 AssetEntity
374
305
```
375
306
376
307
如果不想保留文件,可以在操作完成(上传完或业务处理完)后进行删除:
@@ -387,14 +318,17 @@ final List<String> result = await PhotoManager.editor.deleteWithIds([entity.id])
387
318
W/Glide (21133): Failed to find GeneratedAppGlideModule. You should include an annotationProcessor complie dependency on com.github.bumptech.glide:compiler in you application ana a @GlideModule annotated AppGlideModule implementation or LibraryGlideModules will be silently ignored.
388
319
```
389
320
390
- ` Glide ` 通过注解来保证单例,防止单例或版本之间的冲突,而因为` photo_manager ` 使用了` Glide ` 提供部分图片功能,所以使用它的项目必须实现自己的` AppGlideModule ` 。 请移步[ Android] ( #android ) 部分了解如何实现。
321
+ ` Glide ` 通过注解来保证单例,防止单例或版本之间的冲突,
322
+ 而因为 ` photo_manager ` 使用了 ` Glide ` 提供部分图片功能,所以使用它的项目必须实现自己的 ` AppGlideModule ` 。
323
+ 请移步 [ Android] ( #android ) 部分了解如何实现。
391
324
392
325
### 禁用媒体位置权限
393
326
394
327
Android 将默认包含 ` ACCESS_MEDIA_LOCATION ` 权限。
395
328
这个权限是在 Android Q 中引入的。
396
329
如果你的应用不需要这个权限,
397
330
你需要在你的应用中的 ` AndroidManifest.xml ` 中添加以下节点内容:
331
+
398
332
``` xml
399
333
<uses-permission
400
334
android : name =" android.permission.ACCESS_MEDIA_LOCATION"
@@ -406,6 +340,7 @@ Android 将默认包含 `ACCESS_MEDIA_LOCATION` 权限。
406
340
407
341
> IntelliJ IDEA 的每个方面都旨在最大化开发者生产力。结合智能编码辅助与符合人体工程学的设计,让开发不仅高效,更成为一种享受。
408
342
409
- 感谢 [ JetBrains] ( https://www.jetbrains.com/?from=fluttercandies ) 为开源项目提供免费的 [ IntelliJ IDEA] ( https://www.jetbrains.com/idea/?from=fluttercandies ) 等 IDE 的授权。
343
+ 感谢 [ JetBrains] ( https://www.jetbrains.com/?from=fluttercandies ) 为开源项目提供免费的
344
+ [ IntelliJ IDEA] ( https://www.jetbrains.com/idea/?from=fluttercandies ) 等 IDE 的授权。
410
345
411
346
[ <img src =" .github/jetbrains-variant.png " width =" 200 " />] ( https://www.jetbrains.com/?from=fluttercandies )
0 commit comments