adaptive_image_picker 1.0.2 copy "adaptive_image_picker: ^1.0.2" to clipboard
adaptive_image_picker: ^1.0.2 copied to clipboard

A production-grade, zero-permission adaptive image picker for Flutter with pure-Dart cropping, binary-search compression, and native PhotoPicker integration.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:adaptive_image_picker/adaptive_image_picker.dart';
import 'screens/playground_screen.dart';
import 'screens/recipes_screen.dart';
import 'screens/gallery_screen.dart';

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

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

  @override
  State<AdaptiveImagePickerShowcaseApp> createState() => _AdaptiveImagePickerShowcaseAppState();
}

class _AdaptiveImagePickerShowcaseAppState extends State<AdaptiveImagePickerShowcaseApp> {
  ThemeMode _themeMode = ThemeMode.system;

  void _toggleTheme() {
    setState(() {
      _themeMode = _themeMode == ThemeMode.dark ? ThemeMode.light : ThemeMode.dark;
    });
  }

  @override
  Widget build(BuildContext context) {
    const brandSeed = Color(0xFF3F51B5); // Indigo 500

    return MaterialApp(
      title: 'Adaptive Media Picker Studio',
      debugShowCheckedModeBanner: false,
      themeMode: _themeMode,
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: brandSeed,
        brightness: Brightness.light,
        scaffoldBackgroundColor: const Color(0xFFF8F9FE),
        cardTheme: const CardThemeData(color: Colors.white),
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: brandSeed,
        brightness: Brightness.dark,
        scaffoldBackgroundColor: const Color(0xFF111318),
      ),
      home: MainShowcaseScreen(
        onToggleTheme: _toggleTheme,
        isDarkMode: _themeMode == ThemeMode.dark,
      ),
    );
  }
}

class MainShowcaseScreen extends StatefulWidget {
  final VoidCallback onToggleTheme;
  final bool isDarkMode;

  const MainShowcaseScreen({
    super.key,
    required this.onToggleTheme,
    required this.isDarkMode,
  });

  @override
  State<MainShowcaseScreen> createState() => _MainShowcaseScreenState();
}

class _MainShowcaseScreenState extends State<MainShowcaseScreen> {
  int _currentTabIndex = 0;
  final List<AdaptiveFile> _collectedMedia = [];

  void _addMediaItem(AdaptiveFile file) {
    setState(() {
      _collectedMedia.insert(0, file);
    });
  }

  void _addMultipleMedia(List<AdaptiveFile> files) {
    setState(() {
      _collectedMedia.insertAll(0, files);
    });
  }

  void _updateMediaItem(int index, AdaptiveFile updated) {
    setState(() {
      if (index >= 0 && index < _collectedMedia.length) {
        _collectedMedia[index] = updated;
      }
    });
  }

  void _deleteMediaItem(int index) {
    setState(() {
      if (index >= 0 && index < _collectedMedia.length) {
        _collectedMedia.removeAt(index);
      }
    });
  }

  void _clearAllMedia() {
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('Clear Gallery'),
        content: const Text('Are you sure you want to remove all collected media items?'),
        actions: [
          TextButton(onPressed: () => Navigator.pop(ctx), child: const Text('Cancel')),
          FilledButton(
            onPressed: () {
              Navigator.pop(ctx);
              setState(() => _collectedMedia.clear());
            },
            child: const Text('Clear All'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Row(
          children: [
            Container(
              padding: const EdgeInsets.all(6),
              decoration: BoxDecoration(
                color: Theme.of(context).colorScheme.primaryContainer,
                borderRadius: BorderRadius.circular(8),
              ),
              child: Icon(
                Icons.perm_media_rounded,
                size: 20,
                color: Theme.of(context).colorScheme.onPrimaryContainer,
              ),
            ),
            const SizedBox(width: 10),
            const Text(
              'Adaptive Picker',
              style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
            ),
          ],
        ),
        actions: [
          IconButton(
            icon: Icon(widget.isDarkMode ? Icons.light_mode_outlined : Icons.dark_mode_outlined),
            tooltip: 'Toggle Theme',
            onPressed: widget.onToggleTheme,
          ),
        ],
      ),
      body: IndexedStack(
        index: _currentTabIndex,
        children: [
          PlaygroundScreen(onMediaAdded: _addMediaItem),
          RecipesScreen(
            onMediaAdded: _addMediaItem,
            onMultipleMediaAdded: _addMultipleMedia,
          ),
          GalleryScreen(
            files: _collectedMedia,
            onFileUpdated: _updateMediaItem,
            onFileDeleted: _deleteMediaItem,
            onClearAll: _clearAllMedia,
          ),
        ],
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: _currentTabIndex,
        onDestinationSelected: (index) => setState(() => _currentTabIndex = index),
        destinations: [
          const NavigationDestination(
            icon: Icon(Icons.tune_outlined),
            selectedIcon: Icon(Icons.tune_rounded),
            label: 'Studio',
          ),
          const NavigationDestination(
            icon: Icon(Icons.bolt_outlined),
            selectedIcon: Icon(Icons.bolt_rounded),
            label: 'Recipes',
          ),
          NavigationDestination(
            icon: Badge(
              isLabelVisible: _collectedMedia.isNotEmpty,
              label: Text('${_collectedMedia.length}'),
              child: const Icon(Icons.photo_library_outlined),
            ),
            selectedIcon: Badge(
              isLabelVisible: _collectedMedia.isNotEmpty,
              label: Text('${_collectedMedia.length}'),
              child: const Icon(Icons.photo_library_rounded),
            ),
            label: 'Gallery',
          ),
        ],
      ),
    );
  }
}
6
likes
160
points
44
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A production-grade, zero-permission adaptive image picker for Flutter with pure-Dart cropping, binary-search compression, and native PhotoPicker integration.

Repository (GitHub)
View/report issues

Topics

#image-picker #image-cropper #image-compression #camera #photopicker

License

MIT (license)

Dependencies

file_selector, flutter, flutter_web_plugins, http, image, path, path_provider, plugin_platform_interface, web

More

Packages that depend on adaptive_image_picker

Packages that implement adaptive_image_picker