Language: English | 中文
基于微信 UI 的 资源选择器,
基于 photo_manager
实现资源相关功能,
extended_image
用于查看图片,
provider
用于协助管理选择器的状态。
需要拍照及录制视频,请查看示例的详细用法, 并前往 wechat_camera_picker 。
当前的界面设计基于的微信版本:8.x 界面更新将在微信版本更新后随时进行跟进。
注意: 如果你觉得你的自定义实现会在某些程度上帮助其他人实现他们的需求,你可以通过 PR 提交你的自定义实现。 更多信息请参考 贡献自定义实现 。
查看 迁移指南.
- ♻️ 支持基于代理重载的全量自定义
- 💚 99% 的微信风格
- ⚡️ 根据参数可调的性能优化
- 📷 图片资源支持
- 🔬 HEIF 格式图片支持
- 🎥 视频资源支持
- 🎶 音频资源支持
- 1️⃣ 单资源模式
- 💱 国际化支持
- ⏪ RTL 语言支持
- ➕ 特殊 widget 构建支持(前置/后置)
- 🗂 自定义路径排序支持
- 📝 自定义文本构建支持
- ⏳ 自定义筛选规则支持(
photo_manager
) - 🎏 完整的自定义主题
- 💻 支持 MacOS
尽管该库提供了资源的选择,其仍然要求使用者构建自己的方法来处理显示、上传等操作。 如果你在使用该库的过程对某些方法或API有疑问, 请运行示例并查看 photo_manager 对相关方法的使用说明。
<2.5.0 | 2.8.0 | 2.10.0 | |
---|---|---|---|
7.0.0+ | ❌ | ✅ | ✅ |
6.3.0+ | ❌ | ✅ | ✅ |
如果在 flutter pub get
时遇到了 resolve conflict
失败问题,
请使用 dependency_overrides
解决。
将 wechat_assets_picker
添加至 pubspec.yaml
引用。
dependencies:
wechat_assets_picker: ^latest_version
在你的代码中导入:
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
依赖要求项目的安卓原生部分整合至 Android embedding v2, 更多信息请至 Upgrading pre 1.12 Android projects 查看。
需要声明的权限:INTERNET
, READ_EXTERNAL_STORAGE
, WRITE_EXTERNAL_STORAGE
, ACCESS_MEDIA_LOCATION
。
如果你不需要 ACCESS_MEDIA_LOCATION
权限,请参考 禁用媒体位置权限 要进行移除。
如果你发现有一些与 Glide
有关的警告日志输出,那么主项目就需要实现 AppGlideModule
。
请查看 Generated API.
在 ios/Podfile
中指定最低构建版本至 9.0。
platform :ios, '9.0'
将以下内容添加至 info.plist
。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSPhotoLibraryUsageDescription</key>
<string>你的相册权限描述</string>
目前 Flutter 桌面版仍然在开发阶段,所以请注意,任何与桌面版本有关的问题都不会受到技术支持。
-
在
macos/Podfile
中指定最低构建版本至 10.15。 -
使用 Xcode 打开
macos/Runner.xcworkspace
。接着根据下面的截图将最低构建版本提升至 10.15。 -
与 iOS 一样,添加相同的东西到
info.plist
里。
final List<AssetEntity>? result = await AssetPicker.pickAssets(context);
你可以使用 AssetPickerConfig
来调整选择时的行为。
final List<AssetEntity>? result = await AssetPicker.pickAssets(
context,
pickerConfig: const AssetPickerConfig(),
);
AssetPickerConfig
的成员说明:
参数名 | 类型 | 描述 | 默认值 |
---|---|---|---|
selectedAssets | List<AssetEntity>? |
已选的资源。确保不重复选择。 | null |
maxAssets | int |
最多选择的图片数量 | 9 |
pageSize | int |
分页加载时每页加载的资源数量。**必须为网格数的倍数。 | 80 |
gridThumbnailSize | ThumbnailSize |
预览网格的缩略图大小 | ThumbnailSize.square(200) |
pathThumbnailSize | ThumbnailSize |
路径选择器的缩略图大小 | ThumbnailSize.square(80) |
previewThumbnailSize | ThumbnailSize? |
预览时图片的缩略图大小 | null |
requestType | RequestType |
选择器选择资源的类型 | RequestType.common |
specialPickerType | SpecialPickerType? |
提供一些特殊的选择器类型以整合非常规的选择行为 | null |
keepScrollOffset | bool |
选择器是否可以从同样的位置开始选择 | null |
sortPathDelegate | SortPathDelegate<AssetPathEntity>? |
资源路径的排序实现,可自定义路径排序方法 | CommonSortPathDelegate |
filterOptions | FilterOptionGroup? |
允许用户自定义资源过滤条件 | null |
gridCount | int |
选择器网格数量 | 4 |
themeColor | Color? |
选择器的主题色 | Color(0xff00bc56) |
pickerTheme | ThemeData? |
选择器的主题提供,包括查看器 | null |
textDelegate | AssetPickerTextDelegate? |
选择器的文本代理构建,用于自定义文本 | AssetPickerTextDelegate() |
specialItemPosition | SpecialItemPosition |
允许用户在选择器中添加一个自定义item,并指定位置。 | SpecialPosition.none |
specialItemBuilder | SpecialItemBuilder? |
自定义item的构造方法 | null |
loadingIndicatorBuilder | IndicatorBuilder? |
加载器的实现 | null |
selectPredicate | AssetSelectPredicate |
判断资源可否被选择 | null |
shouldRevertGrid | bool? |
判断资源网格是否需要倒序排列 | null |
我们已将常用的调用方法封装在 example 中。
你只能在使用 pickAssetsWithDelegate
方法时使用 keepScrollOffset
的功能。
更多细节请查看示例内的 Keep scroll offset
方法。
想要了解更多关于自定义代理实现的内容,
查阅 example/lib/customs
。
你可以在 example/lib/pages/multi_assets_page.dart
和
example/lib/pages/single_assets_page.dart
找到 List<PickMethod> pickMethods
,
它分别定义了多选和单选可用的选择模式。
在选择资源后,资源会暂存并展示在页面下方。
页面中的最大选择数是 9
,你可以按需修改。
某些模式只能在多选下使用,例如「WeChat Moment」(朋友圈)模式。
一次只能且最多能选择一个资源。
你可以在「Custom」页面尝试自定义的选择器。
目前我们提供了一个基于 Directory
和 File
(与 photo_manager
完全无关)实现的选择器,
以及一个多 Tab 页切换的选择器。
如果你觉得你的实现有价值或能帮助到其他人,欢迎以 PR 的形式进行提交。
更多细节请阅读 [贡献自定义实现][example/lib/customs/CONTRIBUTING.md]
AssetEntityImageProvider
可以为 图片 & 视频 展示缩略图,以及展示 图片的原图。
它的使用方法与常见的 ImageProvider
一致。
Image(image: AssetEntityImageProvider(asset, isOriginal: false))
请查看示例以了解它如何进行展示。
AssetPicker.registerObserve(); // 注册回调
AssetPicker.unregisterObserve(); // 取消注册回调
AssetPickerBuilderDelegate
、AssetPickerViewerBuilderDelegate
、AssetPickerProvider
及
AssetPickerViewerProvider
均已暴露且可重载。使用者可以使用自定义的泛型类型 <A: 资源, P: 路径>
,
配合继承与重载,实现对应抽象类和类中的方法。更多用法请查看示例中的 Custom
页面,该页面包含一个以
<File, Directory>
为类型基础的选择器。
查看 photo_manager#561 了解详细的解决方法。
你不需要获得路径(也许)。
File
对象可以通过 entity.file
或 entity.originFile
获得,
如果需要 Uint8List
则使用 entity.originBytes
。
如果再此之后你仍然需要路径,那么可以通过已获得的 File
对象获取: file.path
。
final File file = await entity.file; // 缩略图或编辑后的视频
final File originFile = await entity.originFile; // 原图或者原视频
final String path = file.path;
final String originPath = originFile.path;
由 photo_manager
传递的 “Recent” 路径,包含了你设备上的所有的 AssetEntity
。
大部分的平台都会将这个路径命名为 “Recent”。尽管我们提供了自定义文字构建的能力,
但是 AssetPathEntity
的名字或属性只能通过 SortPathDelegate
进行更改。
这是你能访问到所有 AssetPathEntity
的唯一方法,或者说,是现阶段我们暴露出来的唯一方法。
若需要更改某一个路径的名字,继承 CommonSortPathDelegate
并实现你自己的构建,
接着像如下代码一样进行编写:
/// 构建你自己的排序
class CustomSortPathDelegate extends CommonSortPathDelegate {
const CustomSortPathDelegate();
@override
void sort(List<AssetPathEntity> list) {
///...///
// 在这里你可以对每个你认为需要的路径进行判断。
// 我们唯一推荐更改的属性是 [name],
// 并且我们不对更改其他属性造成的问题负责。
for (final AssetPathEntity entity in list) {
// 如果这个路径的 `isAll` 为真,则该路径就是你需要的。
if (entity.isAll) {
entity.name = '最近';
}
}
///...///
}
}
将你的构建传递至静态调用方法里,而后你就会看到你自定义了名称的路径。
如果需要使用此库结合一些拍照需求,可通过以下方法将 File
或 Uint8List
转为 AssetEntity
。
final File file = your_file; // 你的 File 对象
final String path = file.path;
final AssetEntity fileEntity = await PhotoManager.editor.saveImageWithPath(
path,
title: basename(path),
); // 存入手机并生成 AssetEntity
final Uint8List data = your_data; // 你的 Uint8List 对象
final AssetEntity imageEntity = await PhotoManager.editor.saveImage(
file.path,
title: '带有后缀的名称.jpg',
); // 存入手机并生成 AssetEntity
注意:如果不想保留文件,请尽量用 File
承载中间操作,
否则在调用 AssetEntity
的删除时,某些系统下会触发系统弹窗事件:
final List<String> result = await PhotoManager.editor.deleteWithIds([entity.id]);
参考文档: flutter_photo_manager#insert-new-item
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.
Glide
通过注解来保证单例,防止单例或版本之间的冲突,
而因为 photo_manager
使用了 Glide
提供部分图片功能,所以使用它的项目必须实现自己的 AppGlideModule
。
请移步 Android 部分了解如何实现。
Android 将默认包含 ACCESS_MEDIA_LOCATION
权限。
这个权限是在 Android Q 中引入的。
如果你的应用不需要这个权限,
你需要在你的应用中的 AndroidManifest.xml
中添加以下节点内容:
<uses-permission
android:name="android.permission.ACCESS_MEDIA_LOCATION"
tools:node="remove"
/>
IntelliJ IDEA 的每个方面都旨在最大化开发者生产力。结合智能编码辅助与符合人体工程学的设计,让开发不仅高效,更成为一种享受。
感谢 JetBrains 为开源项目提供免费的 IntelliJ IDEA 等 IDE 的授权。