flutter_hero_photo_viewer 0.1.0 copy "flutter_hero_photo_viewer: ^0.1.0" to clipboard
flutter_hero_photo_viewer: ^0.1.0 copied to clipboard

Instagram-style photo viewer with a jank-free Hero transition from a cover thumbnail grid: isomorphic Hero endpoints, deferred gesture layer, swipe-to-dismiss, pinch / double-tap zoom, paging.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_hero_photo_viewer/flutter_hero_photo_viewer.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Hero Photo Viewer Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: const GalleryPage(),
    );
  }
}

class DemoPhotoItem {
  const DemoPhotoItem({
    required this.id,
    required this.title,
    required this.thumbUrl,
    required this.fullUrl,
  });

  final String id;
  final String title;
  final String thumbUrl;
  final String fullUrl;
}

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

  static final List<DemoPhotoItem> photos = List.generate(
    12,
    (index) => DemoPhotoItem(
      id: 'photo_$index',
      title: 'Landscape #${index + 1}',
      thumbUrl: 'https://picsum.photos/id/${10 + index}/400/400',
      fullUrl: 'https://picsum.photos/id/${10 + index}/1200/800',
    ),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Hero Photo Viewer'),
      ),
      body: GridView.builder(
        padding: const EdgeInsets.all(8),
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          crossAxisSpacing: 6,
          mainAxisSpacing: 6,
        ),
        itemCount: photos.length,
        itemBuilder: (context, index) {
          final item = photos[index];
          final thumbProvider = NetworkImage(item.thumbUrl);

          return GestureDetector(
            onTap: () {
              HeroPhotoViewer.open(
                context,
                photos: photos.map((p) {
                  return HeroPhoto(
                    image: NetworkImage(p.fullUrl),
                    thumbnail: NetworkImage(p.thumbUrl),
                    heroTag: p.id,
                  );
                }).toList(),
                initialIndex: index,
              );
            },
            child: HeroPhotoThumbnail(
              image: thumbProvider,
              heroTag: item.id,
              fit: BoxFit.cover,
            ),
          );
        },
      ),
    );
  }
}
0
likes
150
points
52
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Instagram-style photo viewer with a jank-free Hero transition from a cover thumbnail grid: isomorphic Hero endpoints, deferred gesture layer, swipe-to-dismiss, pinch / double-tap zoom, paging.

Repository (GitHub)
View/report issues

Topics

#image-viewer #hero #photo-viewer #gallery #zoom

License

MIT (license)

Dependencies

extended_image, flutter, flutter_hooks

More

Packages that depend on flutter_hero_photo_viewer