photo_opener_view 1.0.0 copy "photo_opener_view: ^1.0.0" to clipboard
photo_opener_view: ^1.0.0 copied to clipboard

A powerful and customizable Flutter package for viewing images and videos with beautiful UI styles and animations.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Photo Opener Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const DemoScreen(),
    );
  }
}

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

  // Sample images from Unsplash
  static const List<String> sampleImages = [
    'https://images.unsplash.com/photo-1506748686214-e9df14d4d9d0?w=800',
    'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=800',
    'https://images.unsplash.com/photo-1426604966848-d7adac402bff?w=800',
    'https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=800',
    'https://images.unsplash.com/photo-1447752875215-b2761acb3c5d?w=800',
  ];

  // Sample video
  static const String sampleVideo =
      'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Photo Opener Demo'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Single Image Section
            _buildSectionTitle('Single Image Viewer'),
            const SizedBox(height: 8),
            _buildImageGrid(context),
            const SizedBox(height: 24),

            // Gallery Section
            _buildSectionTitle('Image Gallery'),
            const SizedBox(height: 8),
            _buildGalleryButton(context),
            const SizedBox(height: 24),

            // Video Section
            _buildSectionTitle('Video Player'),
            const SizedBox(height: 8),
            _buildVideoButton(context),
            const SizedBox(height: 24),

            // Style Options Section
            _buildSectionTitle('Different Styles'),
            const SizedBox(height: 8),
            _buildStyleButtons(context),
          ],
        ),
      ),
    );
  }

  Widget _buildSectionTitle(String title) {
    return Text(
      title,
      style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
    );
  }

  Widget _buildImageGrid(BuildContext context) {
    return SizedBox(
      height: 120,
      child: ListView.builder(
        scrollDirection: Axis.horizontal,
        itemCount: sampleImages.length,
        itemBuilder: (context, index) {
          return GestureDetector(
            onTap: () {
              MediaViewer.openImage(
                context,
                sampleImages[index],
                heroTag: 'image_$index',
                style: MediaViewerStyle.modern,
                onShare: () {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Share clicked!')),
                  );
                },
                onDownload: () {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Download clicked!')),
                  );
                },
                onFavorite: () {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Favorite toggled!')),
                  );
                },
              );
            },
            child: Hero(
              tag: 'image_$index',
              child: Container(
                width: 120,
                margin: const EdgeInsets.only(right: 8),
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(12),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withValues(alpha: 0.2),
                      blurRadius: 8,
                      offset: const Offset(0, 4),
                    ),
                  ],
                ),
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(12),
                  child: Image.network(
                    sampleImages[index],
                    fit: BoxFit.cover,
                    loadingBuilder: (context, child, progress) {
                      if (progress == null) return child;
                      return Container(
                        color: Colors.grey[300],
                        child: const Center(child: CircularProgressIndicator()),
                      );
                    },
                  ),
                ),
              ),
            ),
          );
        },
      ),
    );
  }

  Widget _buildGalleryButton(BuildContext context) {
    return ElevatedButton.icon(
      onPressed: () {
        MediaViewer.openImageGallery(
          context,
          sampleImages,
          initialIndex: 0,
          captions: [
            'Beautiful sunset over the ocean',
            'Mountain landscape at dawn',
            'Peaceful forest trail',
            'Misty morning in the valley',
            'Ancient woodland path',
          ],
          showThumbnails: true,
          onShare: () {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Share gallery image!')),
            );
          },
        );
      },
      icon: const Icon(Icons.photo_library),
      label: const Text('Open Gallery (5 images)'),
      style: ElevatedButton.styleFrom(padding: const EdgeInsets.all(16)),
    );
  }

  Widget _buildVideoButton(BuildContext context) {
    return ElevatedButton.icon(
      onPressed: () {
        MediaViewer.openVideo(
          context,
          sampleVideo,
          title: 'Butterfly Video',
          subtitle: 'Nature documentary',
          autoPlay: true,
          looping: true,
          onShare: () {
            ScaffoldMessenger.of(
              context,
            ).showSnackBar(const SnackBar(content: Text('Share video!')));
          },
        );
      },
      icon: const Icon(Icons.play_circle),
      label: const Text('Play Sample Video'),
      style: ElevatedButton.styleFrom(
        padding: const EdgeInsets.all(16),
        backgroundColor: Colors.red[400],
        foregroundColor: Colors.white,
      ),
    );
  }

  Widget _buildStyleButtons(BuildContext context) {
    final styles = [
      ('Modern', MediaViewerStyle.modern, Colors.blue),
      ('Minimal', MediaViewerStyle.minimal, Colors.grey),
      ('Instagram', MediaViewerStyle.instagram, Colors.pink),
      ('Cinematic', MediaViewerStyle.cinematic, Colors.black87),
      ('Glass', MediaViewerStyle.glassmorphism, Colors.purple),
    ];

    return Wrap(
      spacing: 8,
      runSpacing: 8,
      children: styles.map((style) {
        return ElevatedButton(
          onPressed: () {
            MediaViewer.openImage(context, sampleImages[0], style: style.$2);
          },
          style: ElevatedButton.styleFrom(
            backgroundColor: style.$3,
            foregroundColor: Colors.white,
          ),
          child: Text(style.$1),
        );
      }).toList(),
    );
  }
}
4
likes
0
points
165
downloads

Publisher

verified publishersatish.studio

Weekly Downloads

A powerful and customizable Flutter package for viewing images and videos with beautiful UI styles and animations.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

cached_network_image, flutter, photo_view, shimmer, video_player

More

Packages that depend on photo_opener_view