flutter_hero_photo_viewer 0.1.0
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.
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,
),
);
},
),
);
}
}