# Flutter WeChat Camera Picker
[](https://pub.dev/packages/wechat_camera_picker)
[](https://pub.dev/packages/wechat_camera_picker)
[](https://www.codefactor.io/repository/github/fluttercandies/flutter_wechat_camera_picker)
[](https://github.com/fluttercandies/flutter_wechat_camera_picker/actions/workflows/runnable.yml)
[](https://github.com/fluttercandies/flutter_wechat_camera_picker/blob/master/LICENSE)
[](https://github.com/fluttercandies/flutter_wechat_camera_picker/stargazers)
[](https://github.com/fluttercandies/flutter_wechat_camera_picker/network)
[](https://jq.qq.com/?_wv=1027&k=5bcc0gy)
Language: English | [中文](README-ZH.md)
A **camera picker** for Flutter projects based on WeChat's UI,
which is also a separate runnable extension to the
[wechat_assets_picker][wechat_assets_picker pub].
The current WeChat version that UI is based on: `8.0.49`.
UI designs will be updated at any time following the WeChat update.
See the [Migration Guide][] to learn how to migrate between breaking changes.
## Versions compatibility
The package only guarantees that it will work on **the stable version of Flutter**.
We won't update it in real-time to align with other channels of Flutter.
| | 2.8.0 | 3.3.0 | 3.16.0 |
|--------|:-----:|:-----:|:------:|
| 4.2.0+ | ❌ | ❌ | ✅ |
| 4.0.0+ | ❌ | ✅ | ❌ |
| 3.0.0+ | ✅ | ❌ | ❌ |
## Package credits
The package is built from these wonderful packages.
| Name | Features |
|:-----------------------------------|:--------------------------------------------------|
| [photo_manager][photo_manager pub] | The basic abstractions and management for assets. |
| [camera][camera pub] | Captures images and videos. |
| [video_player][video_player pub] | Plays videos and audios correspondingly. |
Their implementation should be relatively stable in the package.
If you've found any issues related to them when using the picker,
submit issues to our issue tracker first.
Table of content
* [Flutter WeChat Camera Picker](#flutter-wechat-camera-picker)
* [Versions compatibility](#versions-compatibility)
* [Package credits](#package-credits)
* [Features ✨](#features-)
* [Screenshots 📸](#screenshots-)
* [READ THIS FIRST ‼️](#read-this-first-)
* [Preparing for use 🍭](#preparing-for-use-)
* [Setup](#setup)
* [Notes 📝](#notes-)
* [Usage 📖](#usage-)
* [Localizations](#localizations)
* [Simple usage](#simple-usage)
* [With configurations](#with-configurations)
* [Using custom `State`s](#using-custom-states)
* [Frequently asked question 💭](#frequently-asked-question-)
* [Why the orientation behavior is strange on iOS?](#why-the-orientation-behavior-is-strange-on-ios)
* [Contributors ✨](#contributors-)
## Features ✨
- ♿ Complete a11y support with _TalkBack_ and _VoiceOver_
- ♻️ Fully implementable with `State`s override
- 🎏 Fully customizable theme based on `ThemeData`
- 💚 Completely WeChat style (even more)
- ⚡️ Adjustable performance with different configurations
- 📷 Picture capturing support
- 🎥 Video recording support
- ⏱ Duration limitation support
- 🔍 Scale when recording support
- ☀️ Exposure adjust support
- 🔍️ Scale with pinch support
- 💱 i18n support
- ⏪ RTL language support
- 🖾 Foreground custom widget builder support
- 🕹️ Intercept saving with a custom process
## Screenshots 📸
|  |  |  |  |  |
|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|
## READ THIS FIRST ‼️
Be aware of the below notices before you start anything:
- Due to understanding the differences and limitations of a single document,
documents will not cover all the contents.
If you find nothing related to your expected features and cannot understand about concepts,
run the example project and check every option first.
It has covered 90% of regular requests with the package.
- The package deeply integrates with the [photo_manager][photo_manager pub] plugin,
make sure you understand these two concepts as much as possible:
- Asset (photos/videos/audio) - [`AssetEntity`](https://pub.dev/documentation/photo_manager/latest/photo_manager/AssetEntity-class.html)
- Assets collection (albums/libraries) - [`AssetPathEntity`](https://pub.dev/documentation/photo_manager/latest/photo_manager/AssetPathEntity-class.html)
When you have questions about related APIs and behaviors,
check [photo_manager's API docs][] for more details.
Most usages are detailed and covered by the [example](example).
Please walk through the [example](example) carefully
before you have any questions.
## Preparing for use 🍭
If you got a `resolve conflict` error when running `flutter pub get`,
please use `dependency_overrides` to fix it.
### Setup
Run `flutter pub add wechat_camera_picker`,
or add `wechat_camera_picker` to `pubspec.yaml` dependencies manually.
```yaml
dependencies:
wechat_camera_picker: ^latest_version
```
The latest **stable** version is:
[](https://pub.dev/packages/wechat_camera_picker)
The latest **dev** version is:
[](https://pub.dev/packages/wechat_camera_picker)
Follow these detailed setup guide before runs:
- [wechat_assets_picker#preparing-for-use](https://github.com/fluttercandies/flutter_wechat_assets_picker#preparing-for-use-)
- [camera#installation](https://pub.dev/packages/camera#installation)
#### Notes 📝
1. When using `NSPhotoLibraryAddUsageDescription` on iOS,
it requires using `onEntitySaving` or `onXFileCaptured` to handle the captured file,
an `AssetEntity` is not available in this circumstance,
obtaining that asset with its ID will lead to a crash.
Then import the package in your code:
```dart
import 'package:wechat_camera_picker/wechat_camera_picker.dart';
```
## Usage 📖
### Localizations
When you're picking assets, the package will obtain the `Locale?`
from your `BuildContext`, and return the corresponding text delegate
of the current language.
Make sure you have a valid `Locale` in your widget tree that can be accessed
from the `BuildContext`. **Otherwise, the default Chinese delegate will be used.**
Embedded text delegates languages are:
* 简体中文 (default)
* English
* Tiếng Việt
If you want to use a custom/fixed text delegate, pass it through the
`CameraPickerConfig.textDelegate`.
### Simple usage
```dart
final AssetEntity? entity = await CameraPicker.pickFromCamera(context);
```
### With configurations
Use `CameraPickerConfig` for more picking behaviors.
```dart
final AssetEntity? entity = await CameraPicker.pickFromCamera(
context,
pickerConfig: const CameraPickerConfig(),
);
```
Fields in `CameraPickerConfig`:
| Name | Type | Description | Default Value |
|-------------------------------|-------------------------------|-------------------------------------------------------------------------------------------------------|--------------------------------------------|
| enableRecording | `bool` | Whether the picker can record video. | `false` |
| onlyEnableRecording | `bool` | Whether the picker can only record video. Only available when `enableRecording` is `true `. | `false` |
| enableTapRecording | `bool` | Whether allow the record can start with single tap. Only available when `enableRecording` is `true `. | `false` |
| enableAudio | `bool` | Whether Whether the picker should record audio. Only available with recording. | `true` |
| enableSetExposure | `bool` | Whether users can set the exposure point by tapping. | `true` |
| enableExposureControlOnPoint | `bool` | Whether users can adjust exposure according to the set point. | `true` |
| enablePinchToZoom | `bool` | Whether users can zoom the camera by pinch. | `true` |
| enablePullToZoomInRecord | `bool` | Whether users can zoom by pulling up when recording video. | `true` |
| enableScaledPreview | `bool` | Whether the camera preview should be scaled during captures. | `false` |
| shouldDeletePreviewFile | `bool` | Whether the preview file will be delete when pop. | `false` |
| shouldAutoPreviewVideo | `bool` | Whether the video should be played instantly in the preview. | `true` |
| maximumRecordingDuration | `Duration?` | The maximum duration of the video recording process. | `const Duration(seconds: 15)` |
| minimumRecordingDuration | `Duration` | The minimum duration of the video recording process. | `const Duration(seconds: 1)` |
| theme | `ThemeData?` | Theme data for the picker. | `CameraPicker.themeData(wechatThemeColor)` |
| textDelegate | `CameraPickerTextDelegate?` | Text delegate that controls text in widgets. | `CameraPickerTextDelegate` |
| resolutionPreset | `ResolutionPreset` | Present resolution for the camera. | `ResolutionPreset.ultraHigh` |
| cameraQuarterTurns | `int` | The number of clockwise quarter turns the camera view should be rotated. | `0` |
| imageFormatGroup | `ImageFormatGroup` | Describes the output of the raw image format. | `ImageFormatGroup.unknown` |
| preferredLensDirection | `CameraLensDirection` | Which lens direction is preferred when first using the camera. | `CameraLensDirection.back` |
| lockCaptureOrientation | `DeviceOrientation?` | Whether the camera should be locked to the specific orientation during captures. | null |
| foregroundBuilder | `ForegroundBuilder?` | The foreground widget builder which will cover the whole camera preview. | null |
| previewTransformBuilder | `PreviewTransformBuilder?` | The widget builder which will transform the camera preview. | null |
| onEntitySaving | `EntitySaveCallback?` | The callback type define for saving entity in the viewer. | null |
| onError | `CameraErrorHandler?` | The error handler when any error occurred during the picking process. | null |
| onXFileCaptured | `XFileCapturedCallback?` | The callback type definition when the XFile is captured by the camera. | null |
| onMinimumRecordDurationNotMet | `VoidCallback?` | The callback when the recording is not met the minimum recording duration. | null |
| onPickConfirmed | `void Function(AssetEntity)?` | The callback when picture is taken or video is confirmed. | null |
| permissionRequestOption | `PermissionRequestOption?` | The permission request option when saving the captured file using the `photo_manager` package. | null |
### Using custom `State`s
All user interfaces can be customized through custom `State`s, including:
- `CameraPickerState`
- `CameraPickerViewerState`
After overriding `State`s, pass them through the picking method, more specifically:
- `CameraPicker.pickFromCamera(createPickerState: () => CustomCameraPickerState());`
- `CameraPickerViewer.pushToViewer(..., createViewerState: () => CustomCameraPickerViewerState());`
## Frequently asked question 💭
### Why the orientation behavior is strange on iOS?
Currently, the preview is not correctly synced on the iOS.
You can find more details in this issue:
https://github.com/flutter/flutter/issues/89216 .
Other than that, please submit issues to describe your question.
## Contributors ✨
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome!
[wechat_assets_picker pub]: https://pub.dev/packages/wechat_assets_picker
[photo_manager pub]: https://pub.dev/packages/photo_manager
[camera pub]: https://pub.dev/packages/camera
[video_player pub]: https://pub.dev/packages/video_player
[Migration Guide]: https://github.com/fluttercandies/flutter_wechat_camera_picker/blob/main/guides/migration_guide.md
[photo_manager's API docs]: https://pub.dev/documentation/photo_manager/latest/