simple_gallery 0.0.3 copy "simple_gallery: ^0.0.3" to clipboard
simple_gallery: ^0.0.3 copied to clipboard

An easy way to display widgets as a gallery in full-screen with Hero animation, including pinch, zoom, drag & double tap to zoom.

simple_gallery #

An easy way to display widgets as a gallery in full-screen with Hero animation, including pinch, zoom, drag & double tap to zoom.

It also can show any widgets, such as Image, Container, Text, a SVG or Video,...

Features #

  • Show a list of widgets in GridView (Allow to custom the GridView properties)
  • Allow to custom each item in GridView using itemBuilder
  • By clicking to GridView item to show each detail widget in full-screen in a PageView
  • Allow to custom the detail widget using detailDecoration
  • Use pinch & zoom to zoom in and out of images(widgets)
  • Enable to drag up & down the detail widget with opacity background to back to GridView with Hero animation
  • Allow to scroll with page snap to view each detail widget in PageView
  • Fully customizable loading/progress indicator
  • Allow double tapping to zoom
  • No dependencies besides Flutter

Simple Gallery Demo

Installation #

Add simple_gallery as a dependency in your pubspec.yaml file.

Import Simple Gallery:

import 'package:simple_gallery/simple_gallery.dart';

Basic usage #

For example, to show several images with paths:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SimpleGallery<String>(
        items: imageFiles,
        itemSize: (item) => getImageSize(item),
        placeholderBuilder: (context, item) {
            return ColoredBox(
              color: Colors.black38,
              child: Center(child: CircularProgressIndicator()),
            );
          },
        itemBuilder: (context, item, itemSize, viewSize) {
          return Image.file(
            File(item),
            cacheWidth: viewSize.width.round(),
            fit: BoxFit.cover,
          );
        },
        detailDecoration: DetailDecoration(
          detailBuilder: (context, item, itemSize, viewSize) {
            return Image.file(File(item), fit: BoxFit.contain);
          },
          placeholderBuilder: (context, item) {
            return ColoredBox(
              color: Colors.black38,
              child: Center(child: CircularProgressIndicator()),
            );
          },
          pageGap: 16,
        ),
      ),
    );
  }

Note:

itemSize is the size of widget, it is required for Hero animation.

Simple Gallery Demo

Show difference type of widget #

You can use any types for gallery (SimpleGallery

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: SimpleGallery<ImageObject>(
          items: listGalleryObject,
          itemSize:
              (item) =>
                  item.type == ImageType.video
                      ? getImageSizeFromBytes(item.bytes!)
                      : getNetworkImageSize(item.path),
          itemBuilder: (context, item, itemSize, viewSize) {
            final itemType = item.type;
            if (itemType == ImageType.video) {
              return videoThumbnail != null
                  ? Stack(
                    children: [
                      Positioned.fill(
                        child: Image.memory(videoThumbnail!, fit: BoxFit.cover),
                      ),
                      Positioned.fill(
                        child: Icon(Icons.play_circle, color: Colors.black54),
                      ),
                    ],
                  )
                  : CircularProgressIndicator();
            } else {
              return Image.network(
                item.path,
                fit: BoxFit.cover,
                frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
                  if (wasSynchronouslyLoaded || frame != null) {
                    return child;
                  }
                  return Center(
                    child: ColoredBox(
                      color: Colors.black38,
                      child: Center(child: CircularProgressIndicator()),
                    ),
                  );
                },
              );
            }
          },
          placeholderBuilder: (context, item) {
            return ColoredBox(
              color: Colors.black38,
              child: Center(child: CircularProgressIndicator()),
            );
          },
          detailDecoration: DetailDecoration(
            placeholderBuilder: (context, item) {
              return ColoredBox(
                color: Colors.black38,
                child: Center(child: CircularProgressIndicator()),
              );
            },
            detailBuilder: (context, item, itemSize, viewSize) {
              final itemType = item.type;
              if (itemType == ImageType.video) {
                return controller.value.isInitialized
                    ? AspectRatio(
                      aspectRatio: controller.value.aspectRatio,
                      child: VideoPlayer(controller),
                    )
                    : Center(child: CircularProgressIndicator());
              } else {
                return Image.network(
                  item.path,
                  fit: BoxFit.contain,
                  frameBuilder: (
                    context,
                    child,
                    frame,
                    wasSynchronouslyLoaded,
                  ) {
                    if (wasSynchronouslyLoaded || frame != null) {
                      return child;
                    }
                    return Center(
                      child: ColoredBox(
                        color: Colors.black38,
                        child: Center(child: CircularProgressIndicator()),
                      ),
                    );
                  },
                );
              }
            },
            pageGap: 16,
          ),
        ),
      ),
    );
  }

Simple Gallery Demo

Or you can replace by any widgets to itemBuilder & detailBuilder:

          itemBuilder: (context, item, itemSize, viewSize) {
            return Stack(
              children: [
                Positioned.fill(
                  child: Image(
                    image: item,
                    fit: BoxFit.cover,
                    frameBuilder: (
                      context,
                      child,
                      frame,
                      wasSynchronouslyLoaded,
                    ) {
                      if (wasSynchronouslyLoaded || frame != null) {
                        return child;
                      }
                      return Center(
                        child: ColoredBox(
                          color: Colors.black38,
                          child: Center(child: CircularProgressIndicator()),
                        ),
                      );
                    },
                  ),
                ),
                Positioned(
                  bottom: 5,
                  right: 5,
                  child: Icon(Icons.favorite, color: Colors.pink),
                ),
              ],
            );
          },

And,

            detailBuilder: (context, item, itemSize, viewSize) {
              return Stack(
                children: [
                  Positioned.fill(
                    child: Image(
                      image: item,
                      fit: BoxFit.contain,
                      frameBuilder: (
                        context,
                        child,
                        frame,
                        wasSynchronouslyLoaded,
                      ) {
                        if (wasSynchronouslyLoaded || frame != null) {
                          return child;
                        }
                        return Center(
                          child: ColoredBox(
                            color: Colors.black38,
                            child: Center(child: CircularProgressIndicator()),
                          ),
                        );
                      },
                    ),
                  ),
                  Positioned(
                    bottom: 5,
                    right: 5,
                    child: Icon(Icons.favorite, color: Colors.pink),
                  ),
                ],
              );
            },

Simple Gallery Demo

Support you custom the GridView of list images with some properties:

   crossAxisCount: 5,
   crossAxisSpacing: 8.0,
   mainAxisSpacing: 8.0,
   childAspectRatio: 1.0,
   padding: const EdgeInsets.all(8.0),

Simple Gallery Demo

Using detailDecoration with backgroundWidget, headerBuilder & footerBuilder to custom the background, placeHolder, header & footer for detail widget in PageView

            backgroundBuilder: (context) => ColoredBox(color: Colors.white),
            headerBuilder: _buildHeaderDetail,
            footerBuilder: _buildFooterDetail,

And,

  Widget _buildFooterDetail(
    BuildContext context,
    List<NetworkImage> items,
    NetworkImage image,
    PageController controller,
  ) {
    return Material(
      color: Colors.black54,
      child: SizedBox(
        height: 86,
        child: Center(
          child: Text(
            'This is Footer',
            style: TextStyle(fontSize: 35, color: Colors.white),
          ),
        ),
      ),
    );
  }

  Widget _buildHeaderDetail(
    BuildContext context,
    List<NetworkImage> items,
    NetworkImage image,
    PageController controller,
  ) {
    return Material(
      color: Colors.black54,
      child: SizedBox(
        height: 86,
        child: Column(
          children: [
            IconButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              icon: Icon(Icons.arrow_back),
            ),
            Expanded(
              child: Text(
                'This is Header',
                style: TextStyle(fontSize: 20, color: Colors.white),
              ),
            ),
          ],
        ),
      ),
    );
  }

Simple Gallery Demo

5
likes
140
points
27
downloads

Documentation

API reference

Publisher

verified publisherhoangphi.dev

Weekly Downloads

An easy way to display widgets as a gallery in full-screen with Hero animation, including pinch, zoom, drag & double tap to zoom.

Repository (GitHub)
View/report issues

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on simple_gallery