gallery_picker_plus 0.0.1+1
gallery_picker_plus: ^0.0.1+1 copied to clipboard
Modern, customizable gallery picker for Flutter with multi-select, recent media, hero transitions, builder-based customization, and album/category views.
gallery_picker_plus #
Modern, customizable gallery picker for Flutter with multi-select, recent media, hero transitions, and builder-based customization.
Built on and inspired by the original
gallery_pickerpackage by FlutterWay. See: gallery_picker on pub.flutter-io.cn.
Features #
- Multi-select images and videos
- Recent media start mode
- Custom hero and multi-media builders
- Bottom-sheet controls via
BottomSheetPanel - Stream listener for selected files
- Collect gallery metadata (albums, media) with filtering
Screenshots and GIFs #
|
|
|
|
Requirements #
- Dart SDK:
^3.9.2 - Flutter:
>=3.3.0
Installation #
Add to your pubspec.yaml:
dependencies:
gallery_picker_plus: ^0.0.1
Then run:
flutter pub get
Platform setup #
iOS
Add the Photo Library usage descriptions to ios/Runner/Info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to your photo library to select media.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app may save media to your photo library.</string>
Make sure your app uses a valid build name/number in pubspec.yaml (e.g., version: 1.0.0+1).
Android
Ensure the following permissions exist in android/app/src/main/AndroidManifest.xml (adjust per min/target SDK):
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<!-- Pre-Android 13 permission: -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
At runtime, request permissions using a package like permission_handler (example below).
Notes:
- For broad compatibility, consider
minSdkVersion25 inandroid/app/build.gradle. - Update Kotlin/AGP if your project is older (e.g., Kotlin 1.6.0, AGP 7.0.4) per your setup.
Quick start #
import 'package:flutter/material.dart';
import 'package:gallery_picker_plus/gallery_picker.dart';
class Demo extends StatefulWidget {
const Demo({super.key});
@override
State<Demo> createState() => _DemoState();
}
class _DemoState extends State<Demo> {
List<MediaFile> selected = [];
Future<void> pick() async {
final media = await GalleryPicker.pickMedia(
context: context,
initSelectedMedia: selected,
extraRecentMedia: selected,
startWithRecent: true,
);
if (media != null) setState(() => selected = media);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Gallery Picker Plus')),
floatingActionButton: FloatingActionButton(
onPressed: pick,
child: const Icon(Icons.add),
),
body: ListView(
children: [
for (final m in selected)
Padding(
padding: const EdgeInsets.all(8),
child: ThumbnailMedia(media: m),
),
],
),
);
}
}
Advanced usage #
Builder mode with custom UI and hero
await GalleryPicker.pickMediaWithBuilder(
multipleMediaBuilder: (medias, context) {
return YourCustomMediasView(medias);
},
heroBuilder: (tag, media, context) {
return Scaffold(
appBar: AppBar(title: const Text('Preview')),
body: Center(
child: Hero(
tag: tag,
child: MediaProvider(
media: media,
width: MediaQuery.of(context).size.width - 50,
height: 300,
),
),
),
);
},
context: context,
startWithRecent: true,
);
PickerScaffold (bottom sheet layout)
Use a scaffold that integrates the picker as a bottom sheet:
import 'package:gallery_picker_plus/gallery_picker.dart';
@override
Widget build(BuildContext context) {
return PickerScaffold(
backgroundColor: Colors.transparent,
onSelect: (media) {},
initSelectedMedia: const [],
config: const Config(),
body: Container(),
);
}
Listen to selected files (stream)
final subscription = GalleryPicker.listenSelectedFiles.listen((files) {
// Handle updated selected files
});
// When done:
GalleryPicker.disposeSelectedFilesListener();
subscription.cancel();
Control the bottom sheet state
await GalleryPicker.openSheet();
final isOpen = GalleryPicker.isSheetOpened; // also: isSheetExpanded, isSheetCollapsed
await GalleryPicker.closeSheet();
Collect gallery metadata (albums/media)
final media = await GalleryPicker.collectGallery();
GalleryPickerBuilder
Update UI based on in-picker selections:
GalleryPickerBuilder(
builder: (selectedFiles, context) {
return Text('Selected: \\${selectedFiles.length}');
},
)
BottomSheetBuilder
Listen to bottom sheet status to toggle UI:
BottomSheetBuilder(
builder: (status, context) {
return FloatingActionButton(
onPressed: () {
if (status.isExpanded) {
GalleryPicker.closeSheet();
} else {
GalleryPicker.openSheet();
}
},
child: Icon(!status.isExpanded ? Icons.open_in_browser : Icons.close_fullscreen),
);
},
)
Permissions example (recommended) #
import 'package:permission_handler/permission_handler.dart';
Future<void> ensureMediaPermissions() async {
final photos = await Permission.photos.request();
final videos = await Permission.videos.request();
if (photos.isGranted && videos.isGranted) return;
await Permission.storage.request();
}
If the user denies permissions, you can present a dedicated page via Config(permissionDeniedPage: ...).
API overview #
Future<List<MediaFile>?> GalleryPicker.pickMedia({...})Future<void> GalleryPicker.pickMediaWithBuilder({...})Stream<List<MediaFile>> GalleryPicker.listenSelectedFilesvoid GalleryPicker.disposeSelectedFilesListener()void GalleryPicker.dispose()Future<GalleryMedia?> GalleryPicker.collectGallery({ locale, mediaType })Future<GalleryMedia?> GalleryPicker.initializeGallery({ locale })- Sheet helpers:
openSheet(),closeSheet(),isSheetOpened,isSheetExpanded,isSheetCollapsed
Key models are exported: MediaFile, GalleryMedia, Medium, GalleryAlbum, Config, plus UI helpers like MediaProvider, ThumbnailMedia, etc.
Ready-to-use widgets #
Handy UI helpers:
// Thumbnails for media files
ThumbnailMedia(media: media);
// Thumbnails for albums
ThumbnailAlbum(album: album);
// Image provider
PhotoProvider(media: media);
// Video provider
VideoProvider(media: media);
Album views #
Render albums and their contents:
final all = await GalleryPicker.collectGallery();
AlbumMediaView(
galleryAlbum: all!.albums.first,
);
AlbumCategoriesView(
albums: all.albums,
);
Troubleshooting #
- iOS crash on permission request: ensure
NSPhotoLibraryUsageDescriptionandNSPhotoLibraryAddUsageDescriptionexist inInfo.plist. - Nothing returns on Android 13+: ensure
READ_MEDIA_IMAGES/READ_MEDIA_VIDEOpermissions and grant them at runtime. - Black thumbnails for videos: ensure
video_thumbnailandvideo_playerare working in your environment.
Publishing to pub.flutter-io.cn #
- Update
pubspec.yamlwith a properversion,description,homepage/repository. - Verify the README renders well on pub.flutter-io.cn (no remote images requiring auth).
- Run a dry run:
dart pub publish --dry-run - Publish:
dart pub publish -f
License #
MIT
Credits #
This plugin builds upon ideas from the original gallery_picker by FlutterWay. Reference: gallery_picker on pub.flutter-io.cn.