Language: English | 中文简体
对标微信的资源选择器,基于photo_manager
实现资源相关功能,extended_image
用于查看图片,provider
用于协助管理选择器的状态。
拍照及录制视频,请查看 example 详细用法,并前往 wechat_camera_picker 。
查看 迁移指南.
- 💚 99%的微信风格
- 📷 图片资源支持
- 🔬HEIC格式图片支持
- 🎥 视频资源支持
- 🎶 音频资源支持
- 1️⃣ 单资源模式
- 💱 国际化支持
- ➕ 特殊 widget 构建支持(前置/后置)
- 🗂 自定义路径排序支持
- 📝 自定义文本构建支持
- ⏳ 自定义筛选规则支持(
photo_manager
) - 🎏 完整的自定义主题
- 💻 支持 MacOS
尽管该库提供了资源的选择,其仍然要求使用者构建自己的方法来处理显示、上传等操作。如果你在使用该库的过程对某些方法或API有疑问,请运行demo并查看photo_manager对相关方法的使用说明。
Flutter SDK:>=1.17.0
。
如果在 flutter pub get
时遇到了失败问题,请使用 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
。
如果你发现有一些与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
里。
参数名 | 类型 | 描述 | 默认值 |
---|---|---|---|
maxAssets | int |
最多选择的图片数量 | 9 |
pageSize | int |
分页加载时每页加载的资源数量。必须为网格数的倍数。 设置为null 可以取消分页。 |
320 (80 * 4) |
pathThumbSize | int |
选择器的缩略图大小 | 80 |
gridCount | int |
选择器网格数量 | 4 |
previewThumbSize | List<int> |
预览时图片的缩略图大小 | null |
requestType | RequestType |
选择器选择资源的类型 | RequestType.image |
specialPickerType | SpecialPickerType |
提供一些特殊的选择器类型以整合非常规的选择行为 | null |
selectedAssets | List<AssetEntity> |
已选的资源。确保不重复选择。如果你允许重复选择,请将其置空。 | null |
themeColor | Color |
选择器的主题色 | Color(0xff00bc56) |
pickerTheme | ThemeData |
选择器的主题提供,包括查看器 | null |
sortPathDelegate | SortPathDeleage |
资源路径的排序实现,可自定义路径排序方法 | CommonSortPathDelegate |
textDelegate | DefaultAssetsPickerTextDelegate |
选择器的文本代理构建,用于自定义文本 | DefaultAssetsPickerTextDelegate() |
filterOptions | FilterOptionGroup |
允许用户自定义资源过滤条件 | null |
specialItemBuilder | WidgetBuilder |
自定义item的构造方法 | null |
specialItemPosition | SpecialItemPosition |
允许用户在选择器中添加一个自定义item,并指定位置。 | SpecialPosition.none |
allowSpecialItemWhenEmpty | bool |
在资源为空时是否允许显示自定义item | false |
routeCurve | Curve |
选择构造路由动画的曲线 | Curves.easeIn |
routeDuration | Duration |
选择构造路由动画的时间 | const Duration(milliseconds: 500) |
final List<AssetEntity> assets = await AssetPicker.pickAssets(context);
或者
AssetPicker.pickAsset(context).then((List<AssetEntity> assets) {
/.../
});
欲了解各种选择器模式,请直接运行 example 查看。
AssetEntityImageProvider
可以为 图片 & 视频 展示缩略图,以及展示 图片的原图。它的使用方法与常见的 ImageProvider
一致。
Image(image: AssetEntityImageProvider(asset, isOriginal: false))
请查看示例以了解它如何进行展示。
AssetPicker.registerObserve(); // 注册回调
AssetPicker.unregisterObserve(); // 取消注册回调
/// Android: Database _id column
/// iOS : `PhotoKit > PHObject > localIdentifier`
String id;
/// Android: `MediaStore.MediaColumns.DISPLAY_NAME`
/// iOS : `PHAssetResource.filename`. Nullable
/// If you must need it, See [FilterOption.needTitle] or use [titleAsync].
String title;
/// Android: title
/// iOS : [PHAsset valueForKey:@"filename"]
Future<String> get titleAsync;
/// * 1: [AssetType.image]
/// * 2: [AssetType.video]
/// * 3: [AssetType.audio]
/// * default: [AssetType.other]
AssetType get type;
/// Asset type int value.
int typeInt;
/// Duration of video, the unit is second.
/// If [type] is [AssetType.image], then it's value is 0.
/// See also: [videoDuration].
int duration;
/// Width of the asset.
int width;
/// Height of the asset.
int height;
/// Location information when shooting. Nullable.
/// When the device is Android 10 or above, it's ALWAYS null.
/// See also: [longitude].
double get latitude => _latitude ?? 0;
/// Also with a setter.
/// Get lat/lng from `MediaStore`(Android) / `Photos`(iOS).
/// In Android Q, this comes from EXIF.
Future<LatLng> latlngAsync();
/// Get [File] object.
/// Notice that this is not the origin file, so when it comes to some
/// scene like reading a GIF's file, please use `originFile`, or you'll
/// get a JPG.
Future<File> get file async;
/// Get the original [File] object.
Future<File> get originFile async;
/// The raw data for the entity, it may be large.
/// This property is NOT RECOMMENDED for video assets.
Future<Uint8List> get originBytes;
/// The thumbnail data for the entity. Usually use for displaying a thumbnail image widget.
Future<Uint8List> get thumbData;
/// Get thumbnail data with specific size.
Future<Uint8List> thumbDataWithSize(
int width,
int height, {
ThumbFormat format = ThumbFormat.jpeg,
int quality = 100,
});
/// Get the asset's size. Nullable if the manager is null,
Size get size;
/// If the asset is deleted, return false.
Future<bool> get exists => PhotoManager._assetExistsWithId(id);
/// The url is provided to some video player. Such as [flutter_ijkplayer](https://pub.dev/packages/flutter_ijkplayer)
///
/// Android: `content://media/external/video/media/894857`
/// iOS : `file:///var/mobile/Media/DCIM/118APPLE/IMG_8371.MOV` in iOS.
Future<String> getMediaUrl();
/// Refresh the properties for the entity.
Future<AssetEntity> refreshProperties() async;
dartx
或其他依赖可能因为某些原因使用了与你的项目不同的版本。如果你遇到了与下面内容类似的错误::
Because dartx >=0.2.0 <0.5.0 depends on collection >=1.14.11 <1.15.0 and every version of flutter from sdk depends on collection 1.15.0-nullsafety, dartx >=0.2.0 <0.5.0 is incompatible with flutter from sdk.
So, because wechat_assets_picker_demo depends on both flutter any from sdk and dartx ^0.4.2, version solving failed.
将以下代码添加至你的 pubspec.yaml
:
dependency_overrides:
dartx: ^0.4.2
你不需要获得路径(也许)。
File
对象可以通过 entity.originFile
获得,如果需要 Uint8List
则使用 entity.originBytes
。
如果再此之后你仍然需要路径,那么可以通过已获得的 File
对象获取: file.absolutePath
。
由 photo_manager
传递的 “Recent” 路径,包含了您设备上的所有的 AssetEntity
。大部分的平台都会将这个路径命名为 “Recent”。尽管我们提供了自定义文字构建的能力,但是 AssetPathEntity
的名字或属性只能通过 SortPathDelegate
进行更改。这是你能访问到所有 AssetPathEntity
的唯一方法,或者说,是现阶段我们暴露出来的唯一方法。
若需要更改某一个路径的名字,继承 SortPathDelegate
并实现你自己的构建,接着像如下代码一样进行编写:
/// 构建你自己的排序
class CustomSortPathDelegate extends SortPathDelegate {
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 Uint8List byteData = await file.readAsBytes(); // 转为Uint8List
final AssetEntity imageEntity = await PhotoManager.editor.saveImage(byteData); // 存入手机并生成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部分了解如何实现。