piccolo_file_picker 0.0.4 copy "piccolo_file_picker: ^0.0.4" to clipboard
piccolo_file_picker: ^0.0.4 copied to clipboard

A versatile Flutter package for picking images, videos, and documents with filtering and multi-selection options.

example/lib/main.dart

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:piccolo_file_picker/piccolo_file_picker.dart';
import 'package:path/path.dart' as p;

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const PiccoloFilePickerExample(),
    ),
  );
}

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

  @override
  State<PiccoloFilePickerExample> createState() => _PiccoloFilePickerExampleState();
}

class _PiccoloFilePickerExampleState extends State<PiccoloFilePickerExample> implements PiccoloPickerListener {
  final Map<FileType, String> _selectedFiles = {};
  late final PiccoloPickerHandler _pickerHandler;

  @override
  void initState() {
    super.initState();
    _pickerHandler = PiccoloPickerHandler(this);
  }

  @override
  void onFilePicked(dynamic result, {bool isList = false}) {
    if (result == null) return;

    setState(() {
      if (isList) {
        _selectedFiles[FileType.multiple] = (result as List<String>).map(p.basename).join(', ');
      } else {
        _selectedFiles[_currentType] = result.toString();
      }
    });
  }

  FileType _currentType = FileType.camera;

  void _pickFile(FileType type) {
    _currentType = type;
    switch (type) {
      case FileType.camera:
        _pickerHandler.pickImageFromCamera();
      case FileType.gallery:
        _pickerHandler.pickImageFromGallery();
      case FileType.videoCamera:
        _pickerHandler.pickVideoFromCamera();
      case FileType.videoGallery:
        _pickerHandler.pickVideoFromGallery();
      case FileType.single:
        _pickerHandler.pickFileFromStorage();
      case FileType.multiple:
        _pickerHandler.pickFileFromStorage(allowMultiple: true);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.green[100],
      appBar: AppBar(
        elevation: 0,
        backgroundColor: Color(0xFF159e0e),
        title: const Text(
          'Piccolo File Picker Example',
          style: TextStyle(color: Colors.white),
        ),
      ),
      body: CustomScrollView(
        slivers: [
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    'Select Files:\n(Supported platform: Android, iOS)',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 16),
                ],
              ),
            ),
          ),
          SliverPadding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            sliver: SliverGrid(
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
                mainAxisSpacing: 12,
                crossAxisSpacing: 12,
                childAspectRatio: 0.85,
              ),
              delegate: SliverChildBuilderDelegate(
                (context, index) {
                  final type = FileType.values[index];
                  return PickerCard(
                    type: type,
                    onTap: () => _pickFile(type),
                  );
                },
                childCount: FileType.values.length,
              ),
            ),
          ),
          if (_selectedFiles.isNotEmpty)
            SliverToBoxAdapter(
              child: Container(
                margin: const EdgeInsets.only(top: 24),
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      'Selected Files',
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 16),
                    ..._selectedFiles.entries.map(
                      (e) => Padding(
                        padding: const EdgeInsets.only(bottom: 12),
                        child: FileCard(
                          type: e.key,
                          path: e.value,
                          onRemove: () => setState(() => _selectedFiles.remove(e.key)),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
        ],
      ),
    );
  }
}

enum FileType {
  camera('Camera\nImage', Icons.camera_alt),
  gallery('Gallery\nImage', Icons.photo_library),
  videoCamera('Camera\nVideo', Icons.videocam),
  videoGallery('Gallery\nVideo', Icons.video_library),
  single('Single\nFile', Icons.file_present),
  multiple('Multiple\nFiles', Icons.folder);

  const FileType(this.label, this.icon);
  final String label;
  final IconData icon;
}

class PickerCard extends StatelessWidget {
  const PickerCard({super.key, required this.type, required this.onTap});

  final FileType type;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) => Card(
        elevation: 2,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(12),
        ),
        child: InkWell(
          onTap: onTap,
          borderRadius: BorderRadius.circular(12),
          child: Padding(
            padding: EdgeInsets.all(Platform.isAndroid ? 12 : 9),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Container(
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    color: Color(0xFF159e0e).withValues(alpha: 0.1),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Icon(
                    type.icon,
                    size: 28,
                    color: Color(0xFF159e0e),
                  ),
                ),
                const SizedBox(height: 12),
                Text(
                  type.label,
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                    fontSize: 13,
                    fontWeight: FontWeight.w500,
                  ),
                ),
              ],
            ),
          ),
        ),
      );
}

class FileCard extends StatelessWidget {
  const FileCard({super.key, required this.type, required this.path, required this.onRemove});

  final FileType type;
  final String path;
  final VoidCallback onRemove;

  @override
  Widget build(BuildContext context) => Container(
        decoration: BoxDecoration(
          color: Colors.grey[50],
          borderRadius: BorderRadius.circular(12),
          border: Border.all(color: Colors.grey[200]!),
        ),
        child: ListTile(
          contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
          leading: Container(
            padding: const EdgeInsets.all(8),
            decoration: BoxDecoration(
              color: Color(0xFF159e0e).withValues(alpha: 0.1),
              borderRadius: BorderRadius.circular(8),
            ),
            child: Icon(
              type.icon,
              color: Color(0xFF159e0e),
            ),
          ),
          title: Text(
            type.label.replaceAll('\n', ' '),
            style: const TextStyle(fontWeight: FontWeight.w500),
          ),
          subtitle: Text(
            p.basename(path),
          ),
          trailing: IconButton(
            icon: const Icon(Icons.close),
            onPressed: onRemove,
            color: Colors.grey[600],
          ),
        ),
      );
}
3
likes
160
points
40
downloads

Publisher

unverified uploader

Weekly Downloads

A versatile Flutter package for picking images, videos, and documents with filtering and multi-selection options.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

file_picker, flutter, image_picker

More

Packages that depend on piccolo_file_picker