gallery_media_picker 0.3.0 copy "gallery_media_picker: ^0.3.0" to clipboard
gallery_media_picker: ^0.3.0 copied to clipboard

A fully customizable and modern Flutter media picker inspired by Instagram. Supports image/video selection, multi-pick, album browsing, and high-performance grid previews using the photo_manager library.

📸 Gallery Media Picker #

Author Pub Version License Platform GitHub stars

A powerful, high-performance Flutter media picker with an Instagram-style interface. Select images, videos, GIFs, and audio directly from the device gallery with fine-grained control over appearance, behavior, and accessibility.

Built on top of photo_manager with native-level optimizations including PMCancelToken cancellation, automatic cache management, and O(1) selection rebuilds.


💫 Support the Project #

If you find this package helpful, please consider giving it a ⭐ on GitHub and liking it on pub.dev!

Your support helps improve and maintain this project! ❤️


✨ Features #

  • 📷 Pick single or multiple images / videos / GIFs / audio
  • 🖼️ Scrollable grid with infinite loading and persistent thumbnail caching
  • 🔎 Album selector (dropdown overlay style)
  • 🎛️ Highly customizable UI (25+ parameters)
  • ✅ Built for Android & iOS
  • 🔍 Automatic GIF badge and video duration overlay
  • ♿ Full accessibility support (semantic labels for screen readers)
  • 🌐 i18n-ready with GalleryMediaPickerTranslations
  • O(1) selection rebuilds — selecting a photo doesn't rebuild the entire grid
  • 🗑️ Native cache cleanup on dispose (PhotoManager.clearFileCache())
  • 🚫 Background task cancellation via PMCancelToken when items are deselected

🚀 Getting Started #

1. Install #

dependencies:
  gallery_media_picker: ^0.2.0

2. Platform Requirements #

Minimum
Flutter >= 3.41.0
Dart SDK >= 3.11.0
photo_manager ^3.8.0

3. Permissions Setup #

The package uses photo_manager for native media access. It is strongly recommended to use permission_handler to request permissions explicitly before displaying the picker.

Android

Add the following permissions to your AndroidManifest.xml:

<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_AUDIO"/>

On older Android versions (API < 33), you may also need:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

iOS

In your Info.plist:

<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to select media.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Allow access to your gallery</string>
import 'package:permission_handler/permission_handler.dart';

Future<void> requestPermissions() async {
  final status = await Permission.photos.request();
  if (!status.isGranted) {
    // Optionally show a dialog or redirect to app settings
  }
}

⚠️ Call this function before using GalleryMediaPicker.


4. Basic Usage #

GalleryMediaPicker(
  pathList: (List<PickedAssetModel> paths) {
    // Handle selected media files
    for (final asset in paths) {
      print('Selected: ${asset.path} (${asset.type})');
    }
  },
  appBarLeadingWidget: const Icon(Icons.close, color: Colors.white),
  mediaPickerParams: MediaPickerParamsModel(
    maxPickImages: 5,
    singlePick: false,
    mediaType: GalleryMediaType.all,
    thumbnailQuality: ThumbnailQuality.high,
  ),
)

5. Advanced Usage (Dark Theme Example) #

GalleryMediaPicker(
  pathList: (List<PickedAssetModel> paths) {
    context.read<MediaProvider>().setPickedFiles(paths);
  },
  mediaPickerParams: MediaPickerParamsModel(
    appBarHeight: 50,
    maxPickImages: 10,
    crossAxisCount: 4,
    childAspectRatio: 1,
    singlePick: false,
    appBarColor: Colors.transparent,
    gridViewBgColor: const Color(0xFF09090B),
    albumTextColor: Colors.white,
    gridPadding: const EdgeInsets.all(2),
    thumbnailBgColor: const Color(0xFF18181B),
    thumbnailBoxFix: BoxFit.cover,
    selectedAlbumIcon: Icons.check_circle_rounded,
    mediaType: GalleryMediaType.image,
    selectedCheckColor: Colors.white,
    albumSelectIconColor: Colors.white,
    selectedCheckBgColor: const Color(0xFF3B82F6),
    selectedAlbumBgColor: Colors.white10,
    albumDropDownBgColor: const Color(0xFF18181B),
    albumSelectTextColor: Colors.white,
    selectedAssetBgColor: const Color(0xFF3B82F6).withOpacity(0.2),
    selectedAlbumTextColor: const Color(0xFF3B82F6),
    gridViewController: _scrollController, // Use a persistent controller!
    thumbnailQuality: ThumbnailQuality.high,
    gridViewPhysics: const BouncingScrollPhysics(),
    translations: const GalleryMediaPickerTranslations(
      noMediaFound: 'No hay archivos multimedia.',
      permissionDenied: 'Permisos denegados.',
    ),
  ),
)

🧩 API Reference #

GalleryMediaPicker Widget #

Property Type Description
pathList Function(List<PickedAssetModel>) Required. Callback triggered on selection change.
appBarLeadingWidget Widget? Optional widget at the leading position of the toolbar.
mediaPickerParams MediaPickerParamsModel Required. Configuration model for all picker behavior & styling.

MediaPickerParamsModel #

Parameter Type Default Description
appBarHeight double 50.0 Height of the top AppBar.
appBarColor Color? null Background color of the AppBar. Falls back to theme.
maxPickImages int 2 Maximum number of items allowed to select.
singlePick bool true Whether only a single item can be picked.
crossAxisCount int 3 Number of columns in the grid.
childAspectRatio double 0.5 Width-to-height ratio of each grid item.
mediaType GalleryMediaType .all Type of media to display (all / image / video / audio).
thumbnailQuality ThumbnailQuality .medium Quality of generated thumbnails.
thumbnailBoxFix BoxFit .cover How thumbnails fit within their boxes.
thumbnailBgColor Color? null Background color of thumbnail containers.
gridViewBgColor Color? null Background color of the entire grid view.
gridPadding EdgeInsets? null Padding applied to the grid view.
gridViewPhysics ScrollPhysics BouncingScrollPhysics() Scroll behavior of the grid.
gridViewController ScrollController? null External scroll controller for the grid.
albumTextColor Color? null Text color of the selected album name.
albumDropDownBgColor Color? null Background color of the album dropdown overlay.
albumSelectIconColor Color? null Icon color inside the album dropdown.
albumSelectTextColor Color? null Text color inside the album dropdown.
selectedAlbumTextColor Color? null Text color of the currently selected album.
selectedAlbumIcon IconData Icons.check Icon shown next to the selected album.
selectedAlbumBgColor Color? null Background of the selected album row.
selectedAssetBgColor Color? null Overlay color applied to selected thumbnails.
selectedCheckColor Color? null Color of the checkmark icon on selected items.
selectedCheckBgColor Color? null Background color behind the selection checkmark.
translations GalleryMediaPickerTranslations (defaults) Override all user-facing strings for i18n.

GalleryMediaType #

Controls which types of media assets are fetched from the device gallery.

Value Description
all Show all media types (images, videos, GIFs, audio).
image Show only image files (includes GIFs).
video Show only video files.
audio Show only audio files.

ThumbnailQuality #

Controls the resolution of native thumbnail generation. Higher quality provides more detail but may impact performance with very large galleries.

Value Pixel Size Description
low 100×100 Fastest loading, lowest detail.
medium 250×250 Good balance for most use cases.
high 400×400 Best quality, recommended for full-screen pickers.

PickedAssetModel #

The data model returned for each selected asset via the pathList callback.

Property Type Description
id String Unique native identifier of the asset.
path String File path to the asset on disk.
type PickedAssetType Asset type: .image, .video, or .other.
file File? File object, if available.
title String? Original filename or title.
width int Width in pixels.
height int Height in pixels.
size Size Original size.
orientationWidth int Orientation-corrected width.
orientationHeight int Orientation-corrected height.
orientationSize Size Orientation-corrected size.
videoDuration Duration Duration (zero for images).
createDateTime DateTime Creation timestamp.
modifiedDateTime DateTime Last modification timestamp.
latitude double? GPS latitude, if available.
longitude double? GPS longitude, if available.
thumbnail Uint8List? Thumbnail bytes, if generated.

GalleryMediaPickerTranslations #

Override all user-facing strings for localization and accessibility.

Property Type Default Description
noMediaFound String 'No media found.' Shown when an album is empty.
recent String 'Recent' Label for the recents album.
tapToOpenSettings String 'Tap to open settings' Settings redirect label.
permissionDenied String 'Permissions denied...' Shown when gallery access is denied.
maxItemsPicked String 'You have already picked %s items.' Toast when selection limit is reached. Use %s for the number.
videoLabel String 'Video' Accessibility label for videos.
imageLabel String 'Image' Accessibility label for images.
gifLabel String 'GIF' Accessibility label for GIFs.
selectedLabel String 'Selected' Accessibility label for selected state.
notSelectedLabel String 'Not selected' Accessibility label for unselected state.

⚡ Performance Architecture #

The picker includes several performance optimizations built into its core:

O(1) Selection Rebuilds #

Each thumbnail uses an internal _SelectionWatcher widget that caches its own selection boolean. When the global selection list changes, only thumbnails whose ownership actually flips trigger a setState. This means selecting one photo in a grid of 10,000 items rebuilds exactly 1 widget, not all visible items.

Persistent Thumbnail Caching with ValueKey #

Each grid item is keyed with ValueKey(asset.id), ensuring Flutter's element tree correctly identifies and reuses cached images during rapid scrolling. This prevents the common "flicker on scroll back" issue where thumbnails would reload from disk.

Native Background Task Cancellation #

When a user deselects a media item, the in-flight native file extraction (loadFile) is automatically cancelled via PMCancelToken.cancelRequest(), preventing wasted CPU/battery on files the user no longer wants.

Automatic Cache Cleanup #

On dispose, PhotoManager.clearFileCache() is called to clean up temporary OS-generated cache files, preventing storage leaks especially on iOS where HEIC/HEVC transcoding creates temporary copies.

Race Condition Protection #

An internal _albumChangeId counter prevents race conditions when rapidly switching between albums or media types, ensuring only the most recent request completes and updates the UI.


📹 Screenshots / Demo #

Personalization #

Dark Setting

dark_settings

Light Setting

light_settings

Custom Setting

custom_settings

No leading widget

no_leading_widget

Album Selection #

album_selection

Pick single file #

pick_single_file

Pick multiple files #

pick_multiple_files

Select media type #

Only videos

only_videos

Only images and GIF

only_images

Quality comparison #

Low

low_quality

Medium

medium_quality

High

high_quality

💬 Contributing #

Pull requests are welcome! If you find bugs or have suggestions, feel free to open an issue.


📄 License #

MIT License — see the LICENSE file for details.

22
likes
140
points
351
downloads

Publisher

unverified uploader

Weekly Downloads

A fully customizable and modern Flutter media picker inspired by Instagram. Supports image/video selection, multi-pick, album browsing, and high-performance grid previews using the photo_manager library.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, oktoast, photo_manager, photo_manager_image_provider

More

Packages that depend on gallery_media_picker