flutter_native_gallery 0.2.2
flutter_native_gallery: ^0.2.2 copied to clipboard
Native photo and video picker with image optimization and media metadata.
flutter_native_gallery #
A native photo and video gallery picker for Flutter with album browsing, pagination, ordered multiple selection, Live Photo detection, image optimization, and media metadata extraction.
Features #
- Requests native photo library permissions.
- Reads albums, photos, videos, and available native metadata.
- Presents a responsive, draggable gallery bottom sheet.
- Opens album selection in a full-height page with safe-area handling.
- Loads large galleries incrementally.
- Supports image-only, video-only, or combined media requests.
- Preserves the order of multiple selections.
- Limits selection to 30 items by default with a configurable maximum.
- Detects Live Photos on supported Apple platforms.
- Shows video duration and Live Photo indicators.
- Provides a configurable HD selection control.
- Adapts the HD control to light, dark, and custom application color schemes.
- Optimizes non-HD images with configurable quality and dimensions.
- Preserves EXIF data when supported.
- Extracts dimensions, dates, duration, MIME type, location, camera, exposure, favorite state, Live Photo state, and serializable EXIF values.
- Exposes configurable labels for localization.
- Provides both a ready-to-use picker and a lower-level gallery controller.
Platform Requirements #
iOS #
Photo library access requires NSPhotoLibraryUsageDescription in Info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is used to select media.</string>
NSPhotoLibraryAddUsageDescription is only required when selected media can
also be written back to the library:
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Photo library access is used to save media.</string>
Android #
Gallery access uses the media permissions supported by each Android version:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
ACCESS_MEDIA_LOCATION allows coordinates to be read when they are present and
the operating system grants access.
Basic Usage #
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter_native_gallery/flutter_native_gallery.dart';
Open the picker and receive the selected assets in selection order:
final List<FlutterNativeGalleryAsset>? selectedAssets =
await FlutterNativeGalleryPicker.show(
context,
config: const FlutterNativeGalleryPickerConfig(
title: 'Recents',
albumPickerTitle: 'Select an album',
cancelLabel: 'Cancel',
highQualityLabel: 'HD',
highQualityTooltip: 'High quality',
sendLabel: 'Select',
requestType: FlutterNativeGalleryRequestType.imagesAndVideos,
maxSelection: 30,
showHighQualityToggle: true,
highQualityInitiallySelected: false,
),
);
A null result means the picker was dismissed. An empty gallery, denied
permission, and limited-library access are handled by the picker UI.
Export Selected Media #
Resolve an asset to a file together with its normalized metadata:
for (final FlutterNativeGalleryAsset asset
in selectedAssets ?? const <FlutterNativeGalleryAsset>[]) {
final FlutterNativeGalleryAssetExport? exported = await asset.export();
if (exported == null) continue;
final File file = exported.file;
final Map<String, dynamic> metadata = exported.toJson();
}
Videos and HD images use their original file. Non-HD images use the default 1920 x 1920 bounds at quality 82. An original file is retained when optimization would produce a larger result.
A Live Photo is a paired still image and motion resource. The single-file export
contains the still image only, so its serialized metadata reports
isLivePhoto: false and preserves the native source state as
originalIsLivePhoto: true. This prevents consumers from treating a static
JPEG or HEIF export as playable Live Photo media.
Customize non-HD image export with FlutterNativeGalleryImageExportOptions:
final FlutterNativeGalleryAssetExport? exported = await asset.export(
imageOptions: const FlutterNativeGalleryImageExportOptions(
quality: 76,
maxWidth: 1600,
maxHeight: 1600,
format: FlutterNativeGalleryImageFormat.automatic,
preserveExif: true,
useOriginalWhenOptimizedFileIsLarger: true,
),
);
The highQuality argument overrides the value selected in the picker for an
individual export:
final FlutterNativeGalleryAssetExport? original = await asset.export(
highQuality: true,
);
Asset Metadata #
Read metadata without exporting or optimizing the file:
final FlutterNativeGalleryAssetMetadata metadata = await asset.metadata();
final bool hasCoordinates = metadata.hasCoordinates;
final String? device = metadata.device;
final String? format = metadata.format;
final Map<String, dynamic> json = metadata.toJson();
Metadata is best effort. Values unavailable from the operating system or source
file remain null or are omitted from toJson().
Available metadata includes:
| Category | Values |
|---|---|
| Identity | Asset id, file name, media type, and relative path. |
| Media | Width, height, aspect ratio, duration, MIME type, format, and file size. |
| Dates | Capture, creation, and modification dates. |
| Native state | Orientation, subtype, favorite, trashed, and Live Photo state. |
| Location | Latitude, longitude, and altitude when available. |
| Camera | Make, model, lens, software, color space, and exposure values. |
| EXIF | Serializable metadata entries exposed by the source file. |
Asset API #
Each FlutterNativeGalleryAsset provides:
| Member | Description |
|---|---|
id |
Native asset identifier. |
title |
Native title or asset id fallback. |
type |
Image, video, audio, or other. |
width / height |
Oriented media dimensions. |
aspectRatio |
Width-to-height ratio when dimensions are valid. |
duration |
Video duration. |
createdAt / modifiedAt |
Native asset dates when available. |
mimeType |
Native MIME type when available. |
isLivePhoto |
Live Photo state on supported Apple platforms. |
highQualitySelected |
HD choice captured when the selection is returned. |
file() |
Resolves the original or an optimized image file. |
export() |
Resolves a file and its normalized metadata. |
metadata() |
Reads metadata without requiring export. |
thumbnail() |
Returns thumbnail bytes at the requested size and quality. |
Request thumbnail bytes directly:
final Uint8List? thumbnail = await asset.thumbnail(
width: 320,
height: 320,
quality: 80,
);
Picker Configuration #
FlutterNativeGalleryPickerConfig controls selection, presentation, and every
visible label.
| Option | Default | Description |
|---|---|---|
controller |
null |
Optional controller used for permissions and gallery access. |
requestType |
imagesAndVideos |
Loads images, videos, or both. |
maxSelection |
30 |
Maximum ordered selection count. |
pageSize |
80 |
Number of assets requested per page. |
initialHeightFactor |
0.58 |
Initial picker height. |
minHeightFactor |
0.34 |
Minimum drag extent before dismissal. |
maxHeightFactor |
0.96 |
Maximum expanded height. |
showHighQualityToggle |
true |
Shows the HD control. |
highQualityInitiallySelected |
false |
Initial HD state. |
title |
Select attachments |
Picker title when no album name is available. |
albumPickerTitle |
Select an album |
Album selection title. |
cancelLabel |
Cancel |
Close action accessibility label. |
highQualityLabel |
HD |
Visible quality label. |
highQualityTooltip |
High quality |
Quality control accessibility label. |
sendLabel |
Send |
Selection confirmation label. |
recentsLabel |
Recents |
Recent-media fallback label. |
emptyLabel |
No media found |
Empty gallery message. |
permissionTitle |
Gallery access needed |
Permission state title. |
permissionMessage |
Allow photo library access to choose media. |
Permission state message. |
openSettingsLabel |
Open settings |
Settings action label. |
limitedAccessLabel |
Manage selected photos |
Limited-library action label. |
Controller API #
FlutterNativeGalleryController exposes gallery access without the picker UI:
const FlutterNativeGalleryController controller =
FlutterNativeGalleryController();
final FlutterNativeGalleryPermissionStatus permission =
await controller.requestPermission();
if (permission.canReadGallery) {
final List<FlutterNativeGalleryAlbum> albums = await controller.albums();
}
Albums expose their native count, cover, and paginated assets. The controller also provides limited-library management, settings access, and cache clearing.
Platform Behavior #
Live Photo detection uses the native asset subtype available on iOS and macOS.
Android does not expose the same subtype, so isLivePhoto remains false.
Detection describes the native library asset; it does not imply that a
single-file export contains the paired motion resource.
Limited photo access can restrict albums, files, and metadata. Coordinates and EXIF values can also be absent even when permission is granted.
License #
MIT License. See LICENSE.