## gallery_picker Gallery Picker is a flutter package that will allow you to pick media file(s), manage and navigate inside your gallery with modern tools and views. ## Features [✔] Modern design [✔] Detailed documentation [✔] Pick a media file [✔] Pick multiple media files [✔] BottomSheet layout [✔] Auto localization for recent tabs [✔] Fetch all media files from your phone [✔] Comprehensively customizable design (desitination page, hero destination page...) [✔] Gallery picker listener [✔] Thumbnail widgets for media files [✔] MediaProvider widgets to view video / image files [✔] Gallery picker StreamBuilder to update your design if selects any file in gallery picker (GalleryPickerBuilder) [✔] Ready-to-use widgets [✔] Examples provided (example/lib/examples) [✔] Permission requests handled within the library [✔] Null-safety You could find the code samples of the given gifs below in `/example/lib/examples` folder.
## Getting started 1) Update kotlin version to `1.6.0` and `classpath 'com.android.tools.build:gradle:7.0.4'` in your `build.gradle` 2) In `android` set the `minSdkVersion` to `25` in your `build.gradle` #### Android Add uses-permission `android/app/src/main/AndroidManifest.xml` file ```xml ``` for android sdk 33 and above ```xml ``` #### Ios Add these configurations to your `ios/Runner/info.plist` file ```xml NSPhotoLibraryUsageDescription Privacy - Photo Library Usage Description NSMotionUsageDescription Motion usage description NSPhotoLibraryAddUsageDescription NSPhotoLibraryAddUsageDescription ``` ## Usage Quick and simple usage example: ### Pick Single File ```dart MediaFile? singleMedia = await GalleryPicker.pickMedia(context: context,singleMedia: true); ``` ### Pick Multiple Files ```dart List? media = await GalleryPicker.pickMedia(context: context); ``` ### Get All Media Files in Gallery ```dart GalleryMedia? allmedia = await GalleryPicker.collectGallery(); ``` ### Listen selected files inside gallery picker ```dart Stream stream = GalleryPicker.listenSelectedFiles; ``` Dispose listener ```dart GalleryPicker.disposeSelectedFilesListener(); ``` ### PickerScaffold Gallery Picker could also work as a bottom sheet. Use PickerScaffold instead your Scaffold. There is an example at `example/lib/examples/bottom_sheet_example.dart` to see how it could be done. ```dart @override Widget build(BuildContext context) { return PickerScaffold( backgroundColor: Colors.transparent, onSelect: (media) {}, initSelectedMedia: initMedia, config: Config(mode: Mode.dark), body: Container(), ) } ``` ### Customizable destination page Within the Gallery Picker you can design a page that will be redirected after selecting any image(s). Note: There are two builder called multipleMediaBuilder and heroBuilder. If you designed both of them, multipleMediaBuilder will be shown after picking multiple media files, heroBuilder will be shown after picking a single media. If you only designed multipleMediaBuilder, multipleMediaBuilder will be shown after picking any file. Use given hero tag to view your Hero image. You can see a simple example below. There is an example at `example/lib/examples/pick_medias_with_builder.dart` to see how it could be done. ```dart GalleryPicker.pickMediaWithBuilder( multipleMediaBuilder: ((media, context) { return Scaffold( appBar: AppBar( title: const Text('Flippers Page'), ), body: GridView.count( crossAxisCount: 3, mainAxisSpacing: 5, crossAxisSpacing: 5, children: [ for (var mediaFile in media) ThumbnailMedia( media: mediaFile, ) ], ), floatingActionButton: FloatingActionButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => MyHomePage( title: "Selected Medias", medias: media, )), ); GalleryPicker.dispose(); }, child: const Icon( Icons.send, color: Colors.white, ), ), ); }), heroBuilder: (tag, media, context) { return Scaffold( appBar: AppBar( title: const Text('Flippers Page'), ), body: Container( color: Colors.lightBlueAccent, padding: const EdgeInsets.all(16.0), alignment: Alignment.topLeft, child: Hero( tag: tag, child: Image.memory(media.thumbnail!), ), ), floatingActionButton: FloatingActionButton( backgroundColor: Colors.orange, onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => MyHomePage( title: "Selected Medias", medias: [media], )), ); GalleryPicker.dispose(); }, child: const Icon( Icons.send, color: Colors.white, ), ), ); }, context: context); ``` ### Dispose Gallery picker ```dart GalleryPicker.dispose(); ``` ## Customize your gallery picker A Config class is provided to user to customize your gallery picker. You can customize any feature you want and select appearance mode. #### Customizable appereance features ```dart List? media = await GalleryPicker.pickMedia( context: context, pageTransitionType: PageTransitionType.rightToLeft config: Config( backgroundColor: Colors.white, permissionDeniedPage:PermissionDeniedPage(), appbarColor: Colors.white, bottomSheetColor: const Color.fromARGB(255, 247, 248, 250), appbarIconColor: const Color.fromARGB(255, 130, 141, 148), underlineColor: const Color.fromARGB(255, 20, 161, 131), selectedMenuStyle: const TextStyle(color: Colors.black), unselectedMenuStyle: const TextStyle(color: Color.fromARGB(255, 102, 112, 117)), textStyle: const TextStyle( color: Color.fromARGB(255, 108, 115, 121), 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: Container( width: 50, height: 50, decoration: const BoxDecoration( shape: BoxShape.circle, color: Color.fromARGB(255, 0, 168, 132), ), child: const Icon( Icons.check, color: Colors.white, ), ), ), ) ``` #### Appearance Mode ```dart List? media = await GalleryPicker.pickMedia( context: context, config: Config( mode: Mode.dark ), ) ``` #### Give an initial selected media files ```dart List? media = await GalleryPicker.pickMedia( context: context, initSelectedMedia: initSelectedMedia, ) ``` #### Give extra media files that will be included in recent You can give extra pictures to appear on the recent page. You should define these files with MediaFile.file() ```dart MediaFile file = MediaFile.file(id: "id", file: File("path"), type: MediaType.image); List? media = await GalleryPicker.pickMedia( context: context, extraRecentMedia: [file], ) ``` #### Select your priority page There are two pages called "Recent" and "Gallery". You could change the initial page. ```dart List? media = await GalleryPicker.pickMedia( context: context, startWithRecent: true, ) ``` ## MediaFile GalleryPicker returns MediaFile list. You can reach out features below. [✔] Medium [✔] Id [✔] MediaType [✔] Thumbnail [✔] Check with thumbnailFailed if fetching thumbnail fails [✔] Check with fileFailed if getting file fails [✔] File [✔] getThumbnail function [✔] getFile function [✔] getData function [✔] Check if the file selected in gallery picker ## Permission Required permissions will be requested when gallery picker is launched. In case of user's rejection of request, the problem will be handled within gallery picker package. ### Customizing Permission Denied Page ```dart Config( permissionDeniedPage: PermissionDeniedPage(), ) ``` ## Ready-to-use widgets ### ThumbnailMedia ```dart ThumbnailMedia( media: media, ) ``` ### ThumbnailAlbum ```dart ThumbnailAlbum( album: album, failIconColor: failIconColor, mode: mode, backgroundColor: backgroundColor, ) ``` ### PhotoProvider ```dart PhotoProvider( media: media, ) ``` ### VideoProvider ```dart VideoProvider( media: media, ) ``` ### MediaProvider MediaProvider works with every media type ```dart MediaProvider( media: media, ) ``` ### GalleryPickerBuilder You can listen and update your design through this builder ```dart GalleryPickerBuilder( builder: (selectedFiles, context) { return child }, ) ``` ## BottomSheetBuilder Use BottomSheetBuilder if you need to listen bottom sheet status to change something in your page. ```dart 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), ); }, ) ``` ### AlbumMediaView View all media files in the album sorted by its creation date ```dart GalleryMedia? allmedia = await GalleryPicker.collectGallery(); ``` ```dart AlbumMediaView( galleryAlbum: allmedia!.albums[0], textStyle: textStyle, ) ``` ### AlbumCategoriesView View all album categories ```dart GalleryMedia? allmedia = await GalleryPicker.collectGallery(); ``` ```dart AlbumCategoriesView( albums: allmedia!.albums, categoryBackgroundColor: categoryBackgroundColor, categoryFailIconColor: categoryFailIconColor, mode: mode, onFocusChange: onFocusChange, onHover: onHover, onLongPress: onLongPress, onPressed: onPressed, ) ``` ## Breaking Changes From 0.2.3 ### BottomSheetLayout changed into PickerScaffold Before: ```dart @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: BottomSheetLayout( config: Config() onSelect: (media) {}, child: Column( children: [ ``` Now: ```dart @override Widget build(BuildContext context) { return PickerScaffold( backgroundColor: Colors.transparent, onSelect: (media) {}, initSelectedMedia: initMedia, config: Config(mode: Mode.dark), body: Container(), ) } ``` ## Examples Check out our examples! ### Standart Gallery Picker `example/lib/examples/gallery_picker_example.dart` ### Pick Media Files With Destination Page `example/lib/examples/pick_medias_with_builder.dart` ### BottomSheet Example `example/lib/examples/bottom_sheet_example.dart` ### WhatsApp Pick Photo Page `example/lib/examples/whatsapp_pick_photo.dart` ## This package was possible to create with: - The [photo_gallery](https://pub.dev/packages/photo_gallery) package - The [transparent_image](https://pub.dev/packages/transparent_image) package - The [get](https://pub.dev/packages/get) package - The [video_player](https://pub.dev/packages/video_player) package - The [intl](https://pub.dev/packages/intl) package - The [platform_info](https://pub.dev/packages/platform_info) package - The [permission_handler](https://pub.dev/packages/permission_handler) package