Language: English | 中文简体
An assets picker which looks like the one in WeChat, based on photo_manager
for asset implementation, extended_image
for image preview, provider
to help controlling the state of the picker.
To take a photo or a video for assets, please check the detailed usage in the example, and head over to wechat_camera_picker .
Thanks goes to these wonderful people (emoji key):
Alex Li 💻 🎨 📖 💡 🤔 🚧 💬 👀 |
Caijinglong 💡 🤔 |
Marcel Schneider 🐛 💻 🤔 |
ganlanshu0211 🐛 🤔 |
JasonHezz 🐛 💻 |
This project follows the all-contributors specification. Contributions of any kind welcome!
- Migration Guide
- Features
- Screenshots
- Preparing for use
- Usage
- Classes Introduction
- Frequent asked question
- Version resolve conflict with
xxx
(e.g.dartx
) - How can I get path from the
AssetEntity
to integrate withFile
object, upload or edit? - How can I change the name of "Recent" or other entities name/properties?
- Create
AssetEntity
fromFile
orUint8List
(rawData) - Console warning 'Failed to find GeneratedAppGlideModule'
- Version resolve conflict with
See Migration Guide.
- 💚 99% simillar to WeChat style.
- 📷 Image asset support
- 🔬HEIC/HEIF Image type support
- 🎥 Video asset support
- 🎶 Audio asset support
- 1️⃣ Single asset mode
- 💱 i18n support
- ➕ Special item builder (prepend/append) support
- 🗂 Custom sort path delegate support
- 📝 Custom text delegate support
- ⏳ Custom filter options support (
photo_manager
) - 🎏 Custom theme entirely
- 💻 MacOS support
Althought the package provide selection for assets, it still require users build their own methods to handle upload, image compress, etc. If you have any question about how to build it, please run the example or refer to photo_manager for API usage.
Flutter SDK: >=1.17.0
.
If you got an error about resolve conflict
when running flutter pub get
, please use dependency_overrides
to solve it. See here .
Add wechat_assets_picker
to pubspec.yaml
dependencies.
dependencies:
wechat_assets_picker: ^latest_version
Then import the package in your code:
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
Required permissions: INTERNET
, READ_EXTERNAL_STORAGE
, WRITE_EXTERNAL_STORAGE
, ACCESS_MEDIA_LOCATION
.
If you found some warning logs with Glide
appearing, then the main project needs an implementation of AppGlideModule
.
See Generated API.
- Define the minimum platform in
ios/Podfile
upper to 9.0.
platform :ios, '9.0'
- Add following content to
info.plist
.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSPhotoLibraryUsageDescription</key>
<string>Replace with your permission description.</string>
Currently flutter desktop is still under development, so please be aware that any issues releated to the desktop version is not yet supported.
- Define the minimum platform in
macos/Podfile
upper to 10.15.
platform :osx, '10.15'
-
Use Xcode to open the
macos/Runner.xcworkspace
. Then follow screenshots to setup the minumum target version upper to 10.15. -
Add the same thing as iOS does into
info.plist
.
Name | Type | Description | Default |
---|---|---|---|
maxAssets | int |
Maximum asset that the picker can pick. | 9 |
pageSize | int |
Assets amount when assets loaded with paging. Must be a multiple of gridCount . Nullable for non paging. |
320 (80 * 4) |
pathThumbSize | int |
The size of thumb data in picker. | 80 |
gridCount | int |
Grid count in picker. | 4 |
previewThumbSize | List<int> |
Thumb size for the preview of images in the viewer. | null |
requestType | RequestType |
Request type for picker. | RequestType.image |
specialPickerType | SpacialPickerType |
Provide some special picker types to integrate un-common pick pattern. | null |
selectedAssets | List<AssetEntity> |
Selected assets. Prevent duplicate selection. If you don't need to prevent duplicate selection, just don't pass it. | null |
themeColor | Color |
Main theme color for the picker | Color(0xff00bc56) |
pickerTheme | ThemeData |
Theme data provider for the picker and the viewer. | null |
sortPathDelegate | SortPathDeleage |
Path entities sort delegate for the picker, sort paths as you want. | CommonSortPathDelegate |
textDelegate | AssetsPickerTextDelegate |
Text delegate for the picker, for customize the texts. | DefaultAssetsPickerTextDelegate() |
filterOptions | FilterOptionGroup |
Allow users to customize assets filter options. | null |
specialItemBuilder | WidgetBuilder |
The widget builder for the special item. | null |
specialItemPosition | SpecialItemPosition |
Allow users set a special item in the picker with several positions. | SpecialItemPosition.none |
allowSpecialItemWhenEmpty | bool |
Whether the special item will display or not when assets is empty. | false |
routeCurve | Curve |
The curve which the picker use to build page route transition. | Curves.easeIn |
routeDuration | Duration |
The duration which the picker use to build page route transition. | const Duration(milliseconds: 500) |
final List<AssetEntity> assets = await AssetPicker.pickAssets(context);
or
AssetPicker.pickAsset(context).then((List<AssetEntity> assets) {
/.../
});
For various type of the picker, head over to the example and run it with no doubt.
The AssetEntityImageProvider
can display the thumb image of images & videos, and the original data of image. Use it like a common ImageProvider
.
Image(image: AssetEntityImageProvider(asset, isOriginal: false))
Check the example for how it displays.
AssetPicker.registerObserve(); // Register callback.
AssetPicker.unregisterObserve(); // Unregister callback.
/// 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;
For some reasons dartx
or other packages may require a different version than yours. If you're facing this issue, and the error looks like:
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.
Please add the code below to make it work.
dependency_overrides:
dartx: ^0.4.2
You don't need it (might be).
You can always request the File
object with entity.originFile
, if Uint8List
then entity.originBytes
.
If you still needs path after requested the File
, get it through file.absolutePath
.
The path entity called "Recent", brought by photo_manager
in the path entities list, includes all AssetEntity
on your device. "Recent" is a system named entity in most of platforms. While we provided ability to customize the text delegate, the name/properties can only be updated with SortPathDelegate
. This is the only way that you have access to all path entities, or the only way that we exposed currently.
To change the name of the path entity, extend the SortPathDelegate
with your own delegate, then write something like the code below:
/// Create your own sort path delegate.
class CustomSortPathDelegate extends SortPathDelegate {
const CustomSortPathDelegate();
@override
void sort(List<AssetPathEntity> list) {
///...///
// In here you can check every path entities if you want.
// The only property we recommend to change is [name],
// And we have no responsibility for issues caused by
// other properties update.
for (final AssetPathEntity entity in list) {
// If the entity `isAll`, that's the "Recent" entity you want.
if (entity.isAll) {
entity.name = 'Whatever you want';
}
}
///...///
}
}
Pass the delegate through the static call method, then you will get a self-named path entity.
In order to combine this package with camera shooting or something related, there's a solution about how to create an AssetEntity
with File
or Uint8List
object.
final File file = your_file; // Your file object
final Uint8List byteData = await file.readAsBytes(); // Convert to Uint8List
final AssetEntity imageEntity = await PhotoManager.editor.saveImage(byteData); // Saved in the device then create an AssetEntity
If you don't want to keep the asset in your device, just delete it after you complete with your process (upload, editing, etc).
final List<String> result = await PhotoManager.editor.deleteWithIds([entity.id]);
ref: 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
needs annotation to keep singleton, prevent conflict between instances and versions, so while the photo manager uses Glide
to implement image features, the project which import this should define its own AppGlideModule
. See Android section for implementation.