gallery_picker_gdx_plus
A community-maintained Flutter package for browsing a device gallery, selecting one or more images or videos, and presenting media with customizable, ready-to-use widgets.
Features
- Modern light and dark gallery interfaces
- Single- and multiple-media selection
- Image, video, or mixed-media filtering
- Recent-media and album views
- Full-page and bottom-sheet layouts
- Locale-aware recent date groups
- Initial selections and additional recent media
- Selection listeners and reactive builders
- Custom destination pages and Hero transitions
- Thumbnail, image, video, and media-provider widgets
- Permission requests and a customizable permission-denied page
- Sound null safety
The example implementations are available in example/lib/examples.
![]() |
![]() |
![]() |
![]() |
Compatibility
| Platform | Minimum supported version |
|---|---|
| Android | API 24 |
| iOS | 13.0 |
| Dart | 3.11.0 |
| Flutter | 3.41.1 |
The package supports Android and iOS. It does not currently provide web, macOS, Windows, or Linux implementations.
Installation
Add the package from pub.dev:
flutter pub add gallery_picker_gdx_plus
Or add it directly to pubspec.yaml:
dependencies:
gallery_picker_gdx_plus: ^0.6.0
Import the public library:
import 'package:gallery_picker_gdx_plus/gallery_picker.dart';
Platform setup
Android
Set your application's minimum SDK to API 24 or newer. In a current Flutter project using Kotlin DSL:
android {
defaultConfig {
minSdk = 24
}
}
Declare the media permissions required by your application in android/app/src/main/AndroidManifest.xml:
<!-- Android 12L (API 32) and earlier -->
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<!-- Android 13 (API 33) and newer -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
Only declare the image or video permission if your application restricts the picker to that media type.
iOS
Set the deployment target to iOS 13.0 or newer and add a photo-library usage description to ios/Runner/Info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access so you can select media.</string>
If the host application also saves media to the library, provide NSPhotoLibraryAddUsageDescription with an explanation appropriate to the app. The picker itself reads the library.
Usage
Pick one media file
pickMedia returns a list. When singleMedia is enabled, the list contains at most one item.
final List<MediaFile>? result = await GalleryPicker.pickMedia(
context: context,
singleMedia: true,
);
final MediaFile? selected =
result == null || result.isEmpty ? null : result.first;
Pick multiple media files
final List<MediaFile>? selected = await GalleryPicker.pickMedia(
context: context,
);
Restrict the picker to images or videos with GalleryMediaType:
final List<MediaFile>? images = await GalleryPicker.pickMedia(
context: context,
mediaType: GalleryMediaType.image,
);
Collect gallery media
final GalleryMedia? gallery = await GalleryPicker.collectGallery(
mediaType: GalleryMediaType.all,
);
Listen for selection changes
final Stream<List<MediaFile>> selections =
GalleryPicker.listenSelectedFiles;
Dispose of the listener when it is no longer needed:
GalleryPicker.disposeSelectedFilesListener();
Use the bottom-sheet layout
Use PickerScaffold in place of a standard Scaffold. A complete example is in bottom_sheet_example.dart.
@override
Widget build(BuildContext context) {
return PickerScaffold(
backgroundColor: Colors.transparent,
onSelect: (media) {},
initSelectedMedia: initialMedia,
config: Config(mode: Mode.dark),
body: const SizedBox.expand(),
);
}
Open and close the sheet programmatically:
await GalleryPicker.openSheet();
await GalleryPicker.closeSheet();
Build a custom destination page
pickMediaWithBuilder can navigate to custom content after selection. heroBuilder is used for a single selection; multipleMediaBuilder handles multiple selections and acts as the fallback when no Hero builder is supplied.
See pick_medias_with_builder.dart for a complete implementation.
await GalleryPicker.pickMediaWithBuilder(
context: context,
multipleMediaBuilder: (media, context) {
return Scaffold(
appBar: AppBar(title: const Text('Selected media')),
body: GridView.count(
crossAxisCount: 3,
children: [
for (final item in media) ThumbnailMedia(media: item),
],
),
);
},
heroBuilder: (tag, media, context) {
return Scaffold(
body: Center(
child: Hero(
tag: tag,
child: MediaProvider(media: media),
),
),
);
},
);
Release the picker controller after a custom flow is complete:
GalleryPicker.dispose();
Configuration
Pass Config to pickMedia, pickMediaWithBuilder, or PickerScaffold to customize appearance and labels.
final List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context,
pageTransitionType: PageTransitionType.rightToLeft,
config: Config(
mode: Mode.light,
backgroundColor: Colors.white,
appbarColor: Colors.white,
bottomSheetColor: const Color(0xFFF7F8FA),
appbarIconColor: const Color(0xFF828D94),
underlineColor: const Color(0xFF14A183),
selectedMenuStyle: const TextStyle(color: Colors.black),
unselectedMenuStyle: const TextStyle(color: Color(0xFF667075)),
textStyle: const TextStyle(
color: Color(0xFF6C7379),
fontWeight: FontWeight.bold,
),
appbarTextStyle: const TextStyle(color: Colors.black),
recents: 'RECENTS',
gallery: 'GALLERY',
lastMonth: 'Last Month',
lastWeek: 'Last Week',
tapPhotoSelect: 'Tap photo to select',
selected: 'Selected',
selectIcon: const Icon(Icons.check),
),
);
Initial selections
final List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context,
initSelectedMedia: initialMedia,
);
Additional recent media
Create local entries with MediaFile.file and pass them through extraRecentMedia:
final MediaFile localFile = MediaFile.file(
id: 'local-id',
file: File('/path/to/image.jpg'),
type: MediaType.image,
);
final List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context,
extraRecentMedia: [localFile],
);
Initial page
The picker contains Recent and Gallery pages. Select the initial page with startWithRecent:
final List<MediaFile>? media = await GalleryPicker.pickMedia(
context: context,
startWithRecent: true,
);
Permission-denied page
Config(
permissionDeniedPage: const MyPermissionDeniedPage(),
)
MediaFile
Picker results are represented by MediaFile. Each object exposes its ID, media type, underlying medium, thumbnail and file state, selection state, and asynchronous helpers including getThumbnail, getFile, and getData.
Ready-to-use widgets
The package exports reusable building blocks for custom gallery experiences:
| Widget | Purpose |
|---|---|
ThumbnailMedia |
Render a media thumbnail |
ThumbnailAlbum |
Render an album thumbnail |
PhotoProvider |
Display an image media file |
VideoProvider |
Display a video media file |
MediaProvider |
Display either supported media type |
GalleryPickerBuilder |
Rebuild from selection changes |
BottomSheetBuilder |
Rebuild from bottom-sheet state |
AlbumMediaView |
Display media in one album |
AlbumCategoriesView |
Display available albums |
Example:
GalleryPickerBuilder(
builder: (selectedFiles, context) {
return Text('${selectedFiles.length} selected');
},
)
Examples
- Standard gallery picker
- Custom destination page
- Bottom-sheet picker
- Multiple-media view
- WhatsApp-style photo page
Run the example application:
cd example
flutter run
Maintained Package
gallery_picker_gdx_plus is a community-maintained continuation of the original gallery_picker project by Furkan Irmak / FlutterWay. This repository continues maintenance because the upstream package is inactive. Original copyright, license, authorship, contribution history, and project credits remain intact.
The current fork is maintained independently and is not presented as an official release from the original author.
Acknowledgements
Thank you to Furkan Irmak, FlutterWay, and all upstream contributors for creating and improving the original project. Thanks also to the fork contributors and to the packages on which this library builds, including:
photo_gallery_gdx_plusvideo_thumbnail_gdx_pluspermission_handlerbottom_sheet_scaffoldtransparent_imagevideo_playergetintl
Feature Requests
Feature requests and Pull Requests are always welcome.
Please read CONTRIBUTING.md and the Code of Conduct before contributing.
Need Help?
For consulting, package integration, plugin maintenance, or Flutter application development, visit gurwinderdevx.com or use one of the maintainer profiles below.
Maintainer
Maintained by Gurwinder Singh.
License
This project is distributed under the MIT License. The original 2022 copyright notice for Furkan Irmak is preserved in the license file.
Libraries
- controller/gallery_controller
- controller/picker_listener
- functions/color
- gallery_picker
- models/config
- models/gallery_album
- models/gallery_media
- models/media_file
- models/media_type
- models/medium
- models/mode
- user_widgets/album_categories_view
- user_widgets/album_media_view
- user_widgets/date_category_view
- user_widgets/gallery_picker_builder
- user_widgets/media_provider
- user_widgets/photo_provider
- user_widgets/thumbnail_album
- user_widgets/thumbnail_media
- user_widgets/video_provider
- views/album_categories_view/album_categories_view
- views/album_view/album_appbar
- views/album_view/album_medias_view
- views/album_view/album_page
- views/album_view/date_category_view
- views/album_view/media_view
- views/album_view/selected_media_thumbnail
- views/album_view/selected_medias_view
- views/gallery_picker_view/gallery_picker_view
- views/gallery_picker_view/gallery_picker_view_bk
- views/gallery_picker_view/permission_denied_view
- views/gallery_picker_view/picker_appbar
- views/gallery_picker_view/reload_gallery
- views/gridview_static
- views/picker_scaffold
- views/thumbnail_media_file



