gallery_picker_plus 0.0.1+1 copy "gallery_picker_plus: ^0.0.1+1" to clipboard
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.

example/lib/main.dart

import 'package:flutter/material.dart';
// ignore: depend_on_referenced_packages
import 'package:gallery_picker_plus/gallery_picker.dart';
import 'package:permission_handler/permission_handler.dart';

import 'examples/multiple_medias.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        brightness: Brightness.light,
        /* light theme settings */
      ),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
        /* dark theme settings */
      ),
      themeMode: ThemeMode.dark,
      home: const MyHomePage(title: "Gallery Picker"),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final List<MediaFile>? medias;
  const MyHomePage({super.key, required this.title, this.medias});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<MediaFile> selectedMedias = [];

  @override
  void initState() {
    if (widget.medias != null) {
      selectedMedias = widget.medias!;
    }
    _ensurePermissions();
    super.initState();
  }

  int pageIndex = 0;
  var controller = PageController(initialPage: 0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Spacer(),
            const Text('These are your selected medias'),
            const Divider(),
            Expanded(
              flex: 5,
              child: Stack(
                children: [
                  if (selectedMedias.isNotEmpty)
                    PageView(
                      controller: controller,
                      children: [for (var media in selectedMedias) Center(child: MediaProvider(media: media))],
                    ),
                  if (selectedMedias.isNotEmpty)
                    Align(
                      alignment: Alignment.centerRight,
                      child: TextButton(
                        onPressed: () {
                          if (pageIndex < selectedMedias.length - 1) {
                            pageIndex++;
                            controller.animateToPage(
                              pageIndex,
                              duration: const Duration(milliseconds: 500),
                              curve: Curves.easeIn,
                            );
                            setState(() {});
                          }
                        },
                        child: const Icon(Icons.chevron_right, size: 100, color: Colors.red),
                      ),
                    ),
                  if (selectedMedias.isNotEmpty)
                    Align(
                      alignment: Alignment.centerLeft,
                      child: TextButton(
                        onPressed: () {
                          if (pageIndex > 0) {
                            pageIndex--;
                            controller.animateToPage(
                              pageIndex,
                              duration: const Duration(milliseconds: 500),
                              curve: Curves.easeIn,
                            );
                            setState(() {});
                          }
                        },
                        child: const Icon(Icons.chevron_left, size: 100, color: Colors.red),
                      ),
                    ),
                ],
              ),
            ),
            SizedBox(
              height: 65,
              child: ListView(
                scrollDirection: Axis.horizontal,
                children: [
                  for (int i = 0; i < selectedMedias.length; i++)
                    Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 5),
                      child: TextButton(
                        onPressed: () {
                          pageIndex = i;
                          controller.animateToPage(
                            pageIndex,
                            duration: const Duration(milliseconds: 500),
                            curve: Curves.easeIn,
                          );
                          setState(() {});
                        },
                        child: Container(
                          width: 65,
                          height: 50,
                          decoration: BoxDecoration(
                            border: Border.all(width: 2, color: pageIndex == i ? Colors.red : Colors.black),
                          ),
                          child: ThumbnailMedia(media: selectedMedias[i]),
                        ),
                      ),
                    ),
                ],
              ),
            ),
            const Spacer(flex: 2),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: pickMedia,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }

  Future<void> pickMedia() async {
    await _ensurePermissions();
    List<MediaFile>? media = await GalleryPicker.pickMedia(
      context: context,
      initSelectedMedia: selectedMedias,
      extraRecentMedia: selectedMedias,
      startWithRecent: true,
    );
    if (media != null) {
      setState(() {
        selectedMedias += media;
      });
    }
  }

  Future<void> _ensurePermissions() async {
    final photos = await Permission.photos.request();
    final videos = await Permission.videos.request();
    if (photos.isGranted && videos.isGranted) return;
    final storage = await Permission.storage.request();
    // No further action; GalleryPicker will handle denial gracefully.
  }

  pickMediaWithBuilder() {
    GalleryPicker.pickMediaWithBuilder(
      multipleMediaBuilder: ((medias, context) {
        return MultipleMediasView(medias);
      }),
      heroBuilder: (tag, media, context) {
        return Scaffold(
          appBar: AppBar(title: const Text('Hero Page')),
          body: Center(
            child: Hero(
              tag: tag,
              child: MediaProvider(media: media, width: MediaQuery.of(context).size.width - 50, height: 300),
            ),
          ),
          floatingActionButton: FloatingActionButton(
            backgroundColor: Colors.blue,
            onPressed: () {
              GalleryPicker.dispose();
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => MyHomePage(title: "Selected Medias", medias: [media]),
                ),
              );
            },
            child: const Icon(Icons.send, color: Colors.white),
          ),
        );
      },
      context: context,
    );
  }

  Future<void> getGalleryMedia() async {
    // ignore: unused_local_variable
    GalleryMedia? allmedia = await GalleryPicker.collectGallery(locale: const Locale("tr"));
  }
}
1
likes
140
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

Modern, customizable gallery picker for Flutter with multi-select, recent media, hero transitions, builder-based customization, and album/category views.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

bottom_sheet_scaffold, device_info_plus, file_picker, flutter, get, intl, page_transition, permission_handler, photo_gallery_plus, plugin_platform_interface, transparent_image, video_player, video_thumbnail

More

Packages that depend on gallery_picker_plus