media_picker_plus 0.0.1+1 copy "media_picker_plus: ^0.0.1+1" to clipboard
media_picker_plus: ^0.0.1+1 copied to clipboard

A Flutter plugin to pick or capture images and videos with quality control options

example/lib/main.dart

import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:media_picker_plus/media_picker_plus.dart';

import 'advanced_example.dart';
import 'media_preview_widgets.dart';

Future<void> main() async {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Media Picker Plus Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const MediaPickerExample(),
    );
  }
}

class MediaPickerExample extends StatefulWidget {
  const MediaPickerExample({super.key});

  @override
  State<MediaPickerExample> createState() => _MediaPickerExampleState();
}

class _MediaPickerExampleState extends State<MediaPickerExample> {
  String? _singleMediaPath;
  List<String> _multipleMediaPaths = [];
  String? _filePath;
  List<String> _multipleFilePaths = [];
  bool _isLoading = false;

  // Single Media Operations
  Future<void> _pickImage() async {
    setState(() => _isLoading = true);
    try {
      final path = await MediaPickerPlus.pickImage(
        options: const MediaOptions(
          imageQuality: 85,
          maxWidth: 2560,
          maxHeight: 1440,
          watermark: '📸 Media Picker Plus',
          watermarkFontSize: 32,
          watermarkPosition: WatermarkPosition.bottomRight,
        ),
      );
      setState(() {
        _singleMediaPath = path;
      });
    } catch (e) {
      _showError('Error picking image: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _pickVideo() async {
    setState(() => _isLoading = true);
    try {
      final path = await MediaPickerPlus.pickVideo(
        options: const MediaOptions(
          maxWidth: 2560,
          maxHeight: 1440,
          watermark: '🎥 Media Picker Plus',
          watermarkFontSize: 28,
          watermarkPosition: WatermarkPosition.topLeft,
          maxDuration: Duration(minutes: 5),
        ),
      );
      setState(() {
        _singleMediaPath = path;
      });
    } catch (e) {
      _showError('Error picking video: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _capturePhoto() async {
    setState(() => _isLoading = true);
    try {
      final path = await MediaPickerPlus.capturePhoto(
        options: const MediaOptions(
          imageQuality: 90,
          maxWidth: 2560,
          maxHeight: 1440,
          watermark: '📷 Captured with Media Picker Plus',
          watermarkFontSize: 24,
          watermarkPosition: WatermarkPosition.bottomCenter,
        ),
      );
      setState(() {
        _singleMediaPath = path;
      });
    } catch (e) {
      _showError('Error capturing photo: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _recordVideo() async {
    setState(() => _isLoading = true);
    try {
      final path = await MediaPickerPlus.recordVideo(
        options: const MediaOptions(
          maxWidth: 2560,
          maxHeight: 1440,
          watermark: '🎬 Recorded with Media Picker Plus',
          watermarkFontSize: 26,
          watermarkPosition: WatermarkPosition.topRight,
          maxDuration: Duration(minutes: 2),
        ),
      );
      setState(() {
        _singleMediaPath = path;
      });
    } catch (e) {
      _showError('Error recording video: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  // Multiple Media Operations
  Future<void> _pickMultipleImages() async {
    setState(() => _isLoading = true);
    try {
      final paths = await MediaPickerPlus.pickMultipleImages(
        options: const MediaOptions(
          imageQuality: 80,
          maxWidth: 2560,
          maxHeight: 1440,
          watermark: '📸 Multiple Images',
          watermarkFontSize: 20,
          watermarkPosition: WatermarkPosition.bottomLeft,
        ),
      );
      setState(() {
        _multipleMediaPaths = List<String>.from(paths ?? []);
      });
    } catch (e) {
      _showError('Error picking multiple images: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _pickMultipleVideos() async {
    setState(() => _isLoading = true);
    try {
      final paths = await MediaPickerPlus.pickMultipleVideos(
        options: const MediaOptions(
          maxWidth: 2560,
          maxHeight: 1440,
          watermark: '🎥 Multiple Videos',
          watermarkFontSize: 22,
          watermarkPosition: WatermarkPosition.middleCenter,
        ),
      );
      setState(() {
        _multipleMediaPaths = List<String>.from(paths ?? []);
      });
    } catch (e) {
      _showError('Error picking multiple videos: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  // File Operations
  Future<void> _pickFile() async {
    setState(() => _isLoading = true);
    try {
      final path = await MediaPickerPlus.pickFile(
        allowedExtensions: ['.pdf', '.doc', '.docx', '.txt', '.csv'],
      );
      setState(() {
        _filePath = path;
      });
    } catch (e) {
      _showError('Error picking file: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  Future<void> _pickMultipleFiles() async {
    setState(() => _isLoading = true);
    try {
      final paths = await MediaPickerPlus.pickMultipleFiles(
        allowedExtensions: [
          '.pdf',
          '.doc',
          '.docx',
          '.txt',
          '.csv',
          '.xls',
          '.xlsx'
        ],
      );
      setState(() {
        _multipleFilePaths = List<String>.from(paths ?? []);
      });
    } catch (e) {
      _showError('Error picking multiple files: $e');
    } finally {
      setState(() => _isLoading = false);
    }
  }

  // Permission Operations
  Future<void> _checkPermissions() async {
    final cameraPermission = await MediaPickerPlus.hasCameraPermission();
    final galleryPermission = await MediaPickerPlus.hasGalleryPermission();

    if (!mounted) return;

    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Permission Status'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
                'Camera Permission: ${cameraPermission ? "✅ Granted" : "❌ Denied"}'),
            const SizedBox(height: 8),
            Text(
                'Gallery Permission: ${galleryPermission ? "✅ Granted" : "❌ Denied"}'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }

  Future<void> _requestPermissions() async {
    final cameraGranted = await MediaPickerPlus.requestCameraPermission();
    final galleryGranted = await MediaPickerPlus.requestGalleryPermission();

    if (!mounted) return;

    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Permission Request Result'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
                'Camera Permission: ${cameraGranted ? "✅ Granted" : "❌ Denied"}'),
            const SizedBox(height: 8),
            Text(
                'Gallery Permission: ${galleryGranted ? "✅ Granted" : "❌ Denied"}'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }

  void _showError(String message) {
    if (!mounted) return;
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        backgroundColor: Colors.red,
      ),
    );
  }

  void _clearSingleMedia() {
    setState(() {
      _singleMediaPath = null;
    });
  }

  void _clearMultipleMedia() {
    setState(() {
      _multipleMediaPaths.clear();
    });
  }

  void _clearSingleFile() {
    setState(() {
      _filePath = null;
    });
  }

  void _clearMultipleFiles() {
    setState(() {
      _multipleFilePaths.clear();
    });
  }

  Widget _buildMediaPreview() {
    if (_singleMediaPath == null) return const SizedBox.shrink();

    final isVideo = _singleMediaPath!.toLowerCase().endsWith('.mp4') ||
        _singleMediaPath!.toLowerCase().endsWith('.mov');

    if (isVideo) {
      return EnhancedVideoPlayer(
        videoPath: _singleMediaPath!,
        title: 'Single Video Preview',
        onClear: _clearSingleMedia,
      );
    } else {
      return EnhancedImagePreview(
        imagePath: _singleMediaPath!,
        title: 'Single Image Preview',
        onClear: _clearSingleMedia,
      );
    }
  }

  Widget _buildMultipleMediaPreview() {
    if (_multipleMediaPaths.isEmpty) return const SizedBox.shrink();

    return Card(
      elevation: 4,
      child: Column(
        children: [
          Container(
            padding: const EdgeInsets.all(12),
            decoration: BoxDecoration(
              color: Theme.of(context).primaryColor.withAlpha(26),
              borderRadius:
                  const BorderRadius.vertical(top: Radius.circular(12)),
            ),
            child: Row(
              children: [
                const Icon(Icons.collections, size: 20),
                const SizedBox(width: 8),
                const Expanded(
                  child: Text(
                    'Multiple Media Preview',
                    style: TextStyle(fontWeight: FontWeight.bold),
                  ),
                ),
                IconButton(
                  icon: const Icon(Icons.clear, size: 20),
                  onPressed: _clearMultipleMedia,
                  tooltip: 'Clear all',
                ),
              ],
            ),
          ),
          SizedBox(
            height: 150,
            child: ListView.builder(
              scrollDirection: Axis.horizontal,
              itemCount: _multipleMediaPaths.length,
              itemBuilder: (context, index) {
                final path = _multipleMediaPaths[index];
                final isVideo = path.toLowerCase().endsWith('.mp4') ||
                    path.toLowerCase().endsWith('.mov');
                return Container(
                  width: 120,
                  margin: const EdgeInsets.all(8),
                  child: isVideo
                      ? EnhancedVideoPlayer(
                          videoPath: path,
                          height: 100,
                          showControls: false,
                          autoPlay: false,
                        )
                      : EnhancedImagePreview(
                          imagePath: path,
                          height: 100,
                          showControls: false,
                        ),
                );
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text('${_multipleMediaPaths.length} files selected'),
          ),
        ],
      ),
    );
  }

  Widget _buildFilePreview() {
    if (_filePath == null) return const SizedBox.shrink();

    return Card(
      child: Column(
        children: [
          const Padding(
            padding: EdgeInsets.all(8.0),
            child: Text(
              'Single File Preview',
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
          ),
          const Icon(Icons.description, size: 64),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(
              'File: ${_filePath!.split('/').last}',
              style: const TextStyle(fontSize: 14),
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(
              'Path: ${_filePath!.length > 50 ? '${_filePath!.substring(0, 50)}...' : _filePath!}',
              style: const TextStyle(fontSize: 12),
            ),
          ),
          ElevatedButton(
            onPressed: _clearSingleFile,
            child: const Text('Clear'),
          ),
        ],
      ),
    );
  }

  Widget _buildMultipleFilePreview() {
    if (_multipleFilePaths.isEmpty) return const SizedBox.shrink();

    return Card(
      child: Column(
        children: [
          const Padding(
            padding: EdgeInsets.all(8.0),
            child: Text(
              'Multiple Files Preview',
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
          ),
          SizedBox(
            height: 120,
            child: ListView.builder(
              itemCount: _multipleFilePaths.length,
              itemBuilder: (context, index) {
                final path = _multipleFilePaths[index];
                final fileName = path.split('/').last;
                return ListTile(
                  leading: const Icon(Icons.description),
                  title: Text(fileName),
                  subtitle: Text(
                    path.length > 50 ? '${path.substring(0, 50)}...' : path,
                    style: const TextStyle(fontSize: 12),
                  ),
                );
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text('${_multipleFilePaths.length} files selected'),
          ),
          ElevatedButton(
            onPressed: _clearMultipleFiles,
            child: const Text('Clear'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Media Picker Plus Example'),
        actions: [
          IconButton(
            icon: const Icon(Icons.science),
            onPressed: () {
              Navigator.of(context).push(
                MaterialPageRoute(
                  builder: (context) => const AdvancedExample(),
                ),
              );
            },
            tooltip: 'Advanced Examples',
          ),
          IconButton(
            icon: const Icon(Icons.info_outline),
            onPressed: () {
              showDialog(
                context: context,
                builder: (context) => AlertDialog(
                  title: const Text('About Media Picker Plus'),
                  content: const Text(
                    'A comprehensive Flutter plugin for:\n\n'
                    '• Picking images and videos from gallery\n'
                    '• Capturing photos and recording videos\n'
                    '• Advanced watermarking for media\n'
                    '• File picking with extension filtering\n'
                    '• Multiple selection support\n'
                    '• Cross-platform: Android, iOS, macOS, Web\n'
                    '• Permission management\n'
                    '• Image resizing and quality control',
                  ),
                  actions: [
                    TextButton(
                      onPressed: () => Navigator.of(context).pop(),
                      child: const Text('OK'),
                    ),
                  ],
                ),
              );
            },
          ),
        ],
      ),
      body: _isLoading
          ? const Center(child: CircularProgressIndicator())
          : SingleChildScrollView(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  // Single Media Operations
                  const Text(
                    'Single Media Operations',
                    style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 16),
                  Row(
                    children: [
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _pickImage,
                          icon: const Icon(Icons.photo_library),
                          label: const Text('Pick Image'),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _pickVideo,
                          icon: const Icon(Icons.video_library),
                          label: const Text('Pick Video'),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 8),
                  Row(
                    children: [
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _capturePhoto,
                          icon: const Icon(Icons.camera_alt),
                          label: const Text('Capture Photo'),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _recordVideo,
                          icon: const Icon(Icons.videocam),
                          label: const Text('Record Video'),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  _buildMediaPreview(),

                  const SizedBox(height: 32),

                  // Multiple Media Operations
                  const Text(
                    'Multiple Media Operations',
                    style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 16),
                  Row(
                    children: [
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _pickMultipleImages,
                          icon: const Icon(Icons.photo_library),
                          label: const Text('Multiple Images'),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _pickMultipleVideos,
                          icon: const Icon(Icons.video_library),
                          label: const Text('Multiple Videos'),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  _buildMultipleMediaPreview(),

                  const SizedBox(height: 32),

                  // File Operations
                  const Text(
                    'File Operations',
                    style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 16),
                  Row(
                    children: [
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _pickFile,
                          icon: const Icon(Icons.folder),
                          label: const Text('Pick File'),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _pickMultipleFiles,
                          icon: const Icon(Icons.folder_open),
                          label: const Text('Multiple Files'),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  _buildFilePreview(),
                  _buildMultipleFilePreview(),

                  const SizedBox(height: 32),

                  // Permission Operations
                  const Text(
                    'Permission Management',
                    style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 16),
                  Row(
                    children: [
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _checkPermissions,
                          icon: const Icon(Icons.security),
                          label: const Text('Check Permissions'),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        child: ElevatedButton.icon(
                          onPressed: _requestPermissions,
                          icon: const Icon(Icons.lock_open),
                          label: const Text('Request Permissions'),
                        ),
                      ),
                    ],
                  ),

                  const SizedBox(height: 32),

                  // Feature Information
                  Card(
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          const Text(
                            'Features Demonstrated',
                            style: TextStyle(
                                fontSize: 18, fontWeight: FontWeight.bold),
                          ),
                          const SizedBox(height: 8),
                          const Text('✅ Image and video picking from gallery'),
                          const Text(
                              '✅ Camera photo capture and video recording'),
                          const Text(
                              '✅ Advanced watermarking with positioning'),
                          const Text('✅ Image quality control and resizing'),
                          const Text('✅ Multiple media selection'),
                          const Text('✅ File picking with extension filtering'),
                          const Text('✅ Permission management'),
                          const Text(
                              '✅ Cross-platform support (Android, iOS, macOS, Web)'),
                          const SizedBox(height: 16),
                          const Text(
                            'Platform Support',
                            style: TextStyle(
                                fontSize: 16, fontWeight: FontWeight.bold),
                          ),
                          const SizedBox(height: 8),
                          Text(
                              'Current Platform: ${kIsWeb ? "Web" : Platform.operatingSystem}'),
                          const Text(
                              '• Android: Full support with advanced features'),
                          const Text(
                              '• iOS: Full support with advanced features'),
                          const Text(
                              '• macOS: Full support with advanced features'),
                          const Text('• Web: Full support with HTML5 APIs'),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
    );
  }
}
0
likes
0
points
160
downloads

Publisher

verified publisherthanhtunguet.info

Weekly Downloads

A Flutter plugin to pick or capture images and videos with quality control options

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, flutter_web_plugins, plugin_platform_interface, web

More

Packages that depend on media_picker_plus

Packages that implement media_picker_plus