image_picker2 1.0.1 copy "image_picker2: ^1.0.1" to clipboard
image_picker2: ^1.0.1 copied to clipboard

A modern, zero-permission Flutter plugin to pick images and videos with OS-level selection limits and native compression.

example/lib/main.dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker2/image_picker2.dart';

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<String> _mediaPaths = [];
  PickerMediaType _selectedType = PickerMediaType.image;
  bool _isLimitReached = false;

  final TextEditingController _limitController = TextEditingController(
    text: '3',
  );
  final TextEditingController _maxWidthController = TextEditingController(
    text: '1000',
  );
  final TextEditingController _qualityController = TextEditingController(
    text: '80',
  );

  Future<void> _pickMedia() async {
    final limit = int.tryParse(_limitController.text) ?? 1;
    final maxWidth = int.tryParse(_maxWidthController.text);
    final quality = int.tryParse(_qualityController.text);

    final List<String>? result = await ImagePicker2.pickMedia(
      limit: limit,
      type: _selectedType,
      maxWidth: maxWidth,
      quality: quality,
    );

    if (!mounted) return;

    if (result != null) {
      setState(() {
        _mediaPaths = result;
        _isLimitReached = _mediaPaths.length == limit;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: Colors.deepPurple,
        brightness: Brightness.light,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('ImagePicker2 Pro'),
          centerTitle: true,
          elevation: 4,
          shadowColor: Colors.black26,
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              Card(
                elevation: 4,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(16),
                ),
                child: Padding(
                  padding: const EdgeInsets.all(20.0),
                  child: Column(
                    children: [
                      Row(
                        children: [
                          const Icon(Icons.settings, color: Colors.deepPurple),
                          const SizedBox(width: 12),
                          const Expanded(
                            child: Text(
                              'Settings',
                              style: TextStyle(
                                fontSize: 18,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ),
                          if (_isLimitReached)
                            const Chip(
                              label: Text('LIMIT REACHED'),
                              backgroundColor: Colors.redAccent,
                              labelStyle: TextStyle(
                                color: Colors.white,
                                fontSize: 10,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                        ],
                      ),
                      const Divider(height: 30),
                      Row(
                        children: [
                          const Expanded(
                            child: Text(
                              'Media Type:',
                              style: TextStyle(fontWeight: FontWeight.w600),
                            ),
                          ),
                          DropdownButton<PickerMediaType>(
                            value: _selectedType,
                            onChanged: (PickerMediaType? newValue) {
                              if (newValue != null)
                                setState(() => _selectedType = newValue);
                            },
                            items: PickerMediaType.values.map((type) {
                              return DropdownMenuItem(
                                value: type,
                                child: Text(type.name.toUpperCase()),
                              );
                            }).toList(),
                          ),
                        ],
                      ),
                      const SizedBox(height: 12),
                      Row(
                        children: [
                          const Expanded(
                            child: Text(
                              'Selection Limit:',
                              style: TextStyle(fontWeight: FontWeight.w600),
                            ),
                          ),
                          SizedBox(
                            width: 60,
                            child: TextField(
                              controller: _limitController,
                              keyboardType: TextInputType.number,
                              textAlign: TextAlign.center,
                              decoration: const InputDecoration(isDense: true),
                            ),
                          ),
                        ],
                      ),
                      if (_selectedType == PickerMediaType.image) ...[
                        const SizedBox(height: 12),
                        Row(
                          children: [
                            const Expanded(
                              child: Text(
                                'Max Width (px):',
                                style: TextStyle(fontWeight: FontWeight.w600),
                              ),
                            ),
                            SizedBox(
                              width: 80,
                              child: TextField(
                                controller: _maxWidthController,
                                keyboardType: TextInputType.number,
                                textAlign: TextAlign.center,
                                decoration: const InputDecoration(
                                  isDense: true,
                                ),
                              ),
                            ),
                          ],
                        ),
                        const SizedBox(height: 12),
                        Row(
                          children: [
                            const Expanded(
                              child: Text(
                                'Compression Quality:',
                                style: TextStyle(fontWeight: FontWeight.w600),
                              ),
                            ),
                            SizedBox(
                              width: 60,
                              child: TextField(
                                controller: _qualityController,
                                keyboardType: TextInputType.number,
                                textAlign: TextAlign.center,
                                decoration: const InputDecoration(
                                  isDense: true,
                                ),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 20),
              ElevatedButton.icon(
                onPressed: _pickMedia,
                icon: const Icon(Icons.add_photo_alternate),
                label: Text(
                  'Open Pro Picker (${_selectedType.name.toUpperCase()})',
                ),
                style: ElevatedButton.styleFrom(
                  minimumSize: const Size(double.infinity, 60),
                  backgroundColor: Colors.deepPurple,
                  foregroundColor: Colors.white,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(12),
                  ),
                  elevation: 6,
                ),
              ),
              const SizedBox(height: 20),
              Expanded(
                child: _mediaPaths.isEmpty
                    ? const Center(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Icon(
                              Icons.photo_library_outlined,
                              size: 64,
                              color: Colors.grey,
                            ),
                            SizedBox(height: 16),
                            Text(
                              'No media selected yet',
                              style: TextStyle(
                                color: Colors.grey,
                                fontSize: 16,
                              ),
                            ),
                          ],
                        ),
                      )
                    : GridView.builder(
                        gridDelegate:
                            const SliverGridDelegateWithFixedCrossAxisCount(
                              crossAxisCount: 3,
                              crossAxisSpacing: 10,
                              mainAxisSpacing: 10,
                              childAspectRatio: 0.8,
                            ),
                        itemCount: _mediaPaths.length,
                        itemBuilder: (context, index) {
                          final path = _mediaPaths[index];
                          final isVideo =
                              path.endsWith('.mp4') ||
                              path.endsWith('.mov') ||
                              path.endsWith('.m4v');

                          return Container(
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(12),
                              boxShadow: const [
                                BoxShadow(
                                  color: Colors.black12,
                                  blurRadius: 4,
                                  offset: Offset(0, 2),
                                ),
                              ],
                            ),
                            child: Column(
                              children: [
                                Expanded(
                                  child: ClipRRect(
                                    borderRadius: const BorderRadius.vertical(
                                      top: Radius.circular(12),
                                    ),
                                    child: isVideo
                                        ? Container(
                                            width: double.infinity,
                                            color: Colors.black87,
                                            child: const Center(
                                              child: Icon(
                                                Icons.movie,
                                                color: Colors.white,
                                                size: 32,
                                              ),
                                            ),
                                          )
                                        : Image.file(
                                            File(path),
                                            width: double.infinity,
                                            fit: BoxFit.cover,
                                          ),
                                  ),
                                ),
                                Container(
                                  width: double.infinity,
                                  padding: const EdgeInsets.symmetric(
                                    vertical: 4,
                                  ),
                                  decoration: const BoxDecoration(
                                    color: Colors.white,
                                    borderRadius: BorderRadius.vertical(
                                      bottom: Radius.circular(12),
                                    ),
                                  ),
                                  child: Text(
                                    '${(File(path).lengthSync() / 1024).toStringAsFixed(0)} KB',
                                    textAlign: TextAlign.center,
                                    style: const TextStyle(
                                      fontSize: 11,
                                      fontWeight: FontWeight.bold,
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          );
                        },
                      ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
2
likes
150
points
124
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A modern, zero-permission Flutter plugin to pick images and videos with OS-level selection limits and native compression.

Homepage

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on image_picker2

Packages that implement image_picker2