image_builder 1.1.4 copy "image_builder: ^1.1.4" to clipboard
image_builder: ^1.1.4 copied to clipboard

A comprehensive Flutter package for handling network images, SVGs, local assets, file images, and memory images with caching and error handling.

example/lib/main.dart

import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:file_picker/file_picker.dart';
import 'package:image_builder/image_builder.dart';

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

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

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

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ImagePicker _picker = ImagePicker();
  File? _selectedImageFromGallery;
  File? _pickedFile;
  Uint8List? _webPickedFileBytes;
  String? _pickedFileName;
  bool _isPickingFile = false;

  /// Helper method to load asset as bytes for memory image demonstration
  Future<Uint8List> _loadAssetAsBytes(String assetPath) async {
    final byteData = await rootBundle.load(assetPath);
    return byteData.buffer.asUint8List();
  }

  /// Check if current platform is mobile (iOS or Android)
  bool get _isMobile => !kIsWeb && (Platform.isIOS || Platform.isAndroid);

  /// Check if current platform is desktop or web
  bool get _isDesktopOrWeb =>
      kIsWeb || Platform.isMacOS || Platform.isWindows || Platform.isLinux;

  /// Pick file using file_picker (works on all platforms)
  Future<void> _pickFile() async {
    if (_isPickingFile) return;

    setState(() {
      _isPickingFile = true;
    });

    try {
      FilePickerResult? result = await FilePicker.platform.pickFiles(
        type: FileType.image,
        allowMultiple: false,
      );

      if (result != null) {
        if (kIsWeb) {
          // On web, we get bytes instead of file paths
          setState(() {
            _webPickedFileBytes = result.files.single.bytes;
            _pickedFileName = result.files.single.name;
            _pickedFile = null;
            _isPickingFile = false;
          });
        } else {
          // On mobile/desktop, we get file paths
          setState(() {
            _pickedFile = File(result.files.single.path!);
            _pickedFileName = result.files.single.name;
            _webPickedFileBytes = null;
            _isPickingFile = false;
          });
        }
      } else {
        setState(() {
          _isPickingFile = false;
        });
      }
    } catch (e) {
      setState(() {
        _isPickingFile = false;
      });
      if (mounted) {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text('Error picking file: $e')));
      }
    }
  }

  /// Pick image from gallery
  Future<void> _pickImageFromGallery() async {
    try {
      final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
      if (image != null) {
        setState(() {
          _selectedImageFromGallery = File(image.path);
        });
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error picking image from gallery: $e')),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: () {
              Navigator.pushReplacement(
                context,
                PageRouteBuilder(
                  pageBuilder: (context, animation1, animation2) =>
                      const MyHomePage(title: 'ImageBuilder Package Example'),
                  transitionDuration: Duration.zero,
                  reverseTransitionDuration: Duration.zero,
                ),
              );
            },
            tooltip: 'Refresh Images',
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            _buildSectionHeader('Network Images'),
            const SizedBox(height: 16),
            _buildTestCase(
              'Standard Network Image',
              ImageBuilder(
                'https://picsum.photos/200/200?random=1',
                width: 200,
                height: 200,
                fit: BoxFit.cover,
                useAdaptiveLoading: true,
                errorWidget: Container(
                  width: 200,
                  height: 200,
                  color: Colors.red[100],
                  child: const Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.error, color: Colors.red, size: 32),
                      SizedBox(height: 8),
                      Text('Failed to load', style: TextStyle(fontSize: 12)),
                    ],
                  ),
                ),
              ),
            ),

            const SizedBox(height: 32),

            _buildSectionHeader('Large Network Image'),
            const SizedBox(height: 16),
            _buildTestCase(
              'Large Image for Slow Loading Example',
              ImageBuilder(
                'https://picsum.photos/2000/1500?random=2',
                width: 250,
                height: 180,
                fit: BoxFit.cover,
                useAdaptiveLoading: true,
                loadingColor: Colors.blue,
                errorWidget: Container(
                  width: 250,
                  height: 180,
                  color: Colors.blue[100],
                  child: const Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.broken_image, color: Colors.blue, size: 32),
                      SizedBox(height: 8),
                      Text(
                        'Large image failed',
                        style: TextStyle(fontSize: 10, color: Colors.blue),
                      ),
                    ],
                  ),
                ),
              ),
            ),

            const SizedBox(height: 32),

            _buildSectionHeader('SVG Images'),
            const SizedBox(height: 16),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Column(
                  children: [
                    ImageBuilder(
                      'assets/icons/android.svg',
                      size: 60,
                      color: Colors.blue,
                    ),
                    const SizedBox(height: 4),
                    const Text('Blue Android', style: TextStyle(fontSize: 12)),
                  ],
                ),
                Column(
                  children: [
                    ImageBuilder('assets/icons/github.svg', size: 60),
                    const SizedBox(height: 4),
                    const Text(
                      'GitHub Original',
                      style: TextStyle(fontSize: 12),
                    ),
                  ],
                ),
              ],
            ),

            const SizedBox(height: 32),

            _buildSectionHeader('Local Images'),
            const SizedBox(height: 16),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Column(
                  children: [
                    _buildTestCase(
                      'Local JPG',
                      ImageBuilder(
                        'assets/images/file_formats.jpg',
                        width: 150,
                        height: 120,
                        fit: BoxFit.cover,
                      ),
                    ),
                  ],
                ),
                Column(
                  children: [
                    _buildTestCase(
                      'Local PNG',
                      ImageBuilder(
                        'assets/images/rectangle.png',
                        width: 150,
                        height: 120,
                        fit: BoxFit.contain,
                      ),
                    ),
                  ],
                ),
              ],
            ),

            const SizedBox(height: 32),

            _buildSectionHeader('Memory Images'),
            const SizedBox(height: 16),
            _buildTestCase(
              'Image from Memory Bytes (Uint8List)',
              FutureBuilder<Uint8List>(
                future: _loadAssetAsBytes('assets/images/photo.jpg'),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return ImageBuilder.memory(
                      snapshot.data!,
                      width: 200,
                      height: 150,
                      fit: BoxFit.cover,
                    );
                  } else if (snapshot.hasError) {
                    return Container(
                      width: 200,
                      height: 150,
                      color: Colors.red[100],
                      child: const Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Icon(Icons.error, color: Colors.red),
                          Text('Failed to load memory image'),
                        ],
                      ),
                    );
                  }
                  return Container(
                    width: 200,
                    height: 150,
                    color: Colors.grey[200],
                    child: const Center(child: CircularProgressIndicator()),
                  );
                },
              ),
            ),

            const SizedBox(height: 32),

            _buildSectionHeader('Device Images (File Constructor)'),
            const SizedBox(height: 16),

            // Platform-specific card - File picker for Desktop/Web
            if (_isDesktopOrWeb)
              _buildTestCase(
                'Pick Image File (Desktop & Web)',
                Column(
                  children: [
                    ElevatedButton.icon(
                      onPressed: _isPickingFile ? null : _pickFile,
                      icon: _isPickingFile
                          ? const SizedBox(
                              width: 16,
                              height: 16,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            )
                          : const Icon(Icons.folder_open),
                      label: Text(
                        _isPickingFile ? 'Picking File...' : 'Pick Image File',
                      ),
                    ),
                    const SizedBox(height: 4),
                    Text(
                      kIsWeb ? 'Web File Picker' : 'Desktop File Picker',
                      style: const TextStyle(fontSize: 11, color: Colors.blue),
                      textAlign: TextAlign.center,
                    ),
                    const SizedBox(height: 8),
                    if (_pickedFile != null || _webPickedFileBytes != null)
                      Column(
                        children: [
                          // For non-web platforms (desktop) use File
                          if (_pickedFile != null && !kIsWeb)
                            ImageBuilder.file(
                              _pickedFile!,
                              width: 200,
                              height: 150,
                              fit: BoxFit.cover,
                            ),
                          // For web platform use memory (since File doesn't work on web)
                          if (_webPickedFileBytes != null && kIsWeb)
                            ImageBuilder.memory(
                              _webPickedFileBytes!,
                              width: 200,
                              height: 150,
                              fit: BoxFit.cover,
                            ),
                          const SizedBox(height: 8),
                          Text(
                            'File: ${_pickedFileName ?? 'Unknown'}',
                            style: const TextStyle(
                              fontSize: 12,
                              color: Colors.grey,
                            ),
                          ),
                          Text(
                            kIsWeb
                                ? '(Using ImageBuilder.memory)'
                                : '(Using ImageBuilder.file)',
                            style: const TextStyle(
                              fontSize: 10,
                              color: Colors.blue,
                            ),
                          ),
                        ],
                      )
                    else
                      Container(
                        width: 200,
                        height: 150,
                        decoration: BoxDecoration(
                          color: Colors.blue[50],
                          borderRadius: BorderRadius.circular(8),
                          border: Border.all(
                            color: Colors.blue,
                            style: BorderStyle.solid,
                          ),
                        ),
                        child: const Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Icon(
                              Icons.folder_open,
                              size: 40,
                              color: Colors.blue,
                            ),
                            SizedBox(height: 8),
                            Text(
                              'Click to pick image file',
                              style: TextStyle(
                                color: Colors.blue,
                                fontSize: 12,
                              ),
                              textAlign: TextAlign.center,
                            ),
                          ],
                        ),
                      ),
                  ],
                ),
              ),

            // Platform-specific card - Gallery picker for Mobile
            if (_isMobile)
              _buildTestCase(
                'Choose from Gallery (Mobile)',
                Column(
                  children: [
                    ElevatedButton.icon(
                      onPressed: _pickImageFromGallery,
                      icon: const Icon(Icons.photo_library),
                      label: const Text('Choose from Gallery'),
                    ),
                    const SizedBox(height: 4),
                    const Text(
                      'Mobile Gallery Access',
                      style: TextStyle(fontSize: 11, color: Colors.green),
                      textAlign: TextAlign.center,
                    ),
                    const SizedBox(height: 8),
                    if (_selectedImageFromGallery != null)
                      Column(
                        children: [
                          ImageBuilder.file(
                            _selectedImageFromGallery!,
                            width: 200,
                            height: 150,
                            fit: BoxFit.cover,
                          ),
                          const SizedBox(height: 8),
                          Text(
                            'File: ${_selectedImageFromGallery!.path.split('/').last}',
                            style: const TextStyle(
                              fontSize: 12,
                              color: Colors.grey,
                            ),
                          ),
                          const Text(
                            '(Using ImageBuilder.file)',
                            style: TextStyle(fontSize: 10, color: Colors.green),
                          ),
                        ],
                      )
                    else
                      Container(
                        width: 200,
                        height: 150,
                        decoration: BoxDecoration(
                          color: Colors.green[50],
                          borderRadius: BorderRadius.circular(8),
                          border: Border.all(
                            color: Colors.green,
                            style: BorderStyle.solid,
                          ),
                        ),
                        child: const Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Icon(
                              Icons.photo_library,
                              size: 40,
                              color: Colors.green,
                            ),
                            SizedBox(height: 8),
                            Text(
                              'Choose from gallery',
                              style: TextStyle(
                                color: Colors.green,
                                fontSize: 12,
                              ),
                              textAlign: TextAlign.center,
                            ),
                          ],
                        ),
                      ),
                  ],
                ),
              ),

            const SizedBox(height: 32),

            _buildSectionHeader('Error Handling'),
            const SizedBox(height: 16),
            _buildTestCase(
              'Non-existent Image URL',
              ImageBuilder(
                'https://this-does-not-exist.com/image.jpg',
                width: 150,
                height: 150,
                errorWidget: Container(
                  width: 150,
                  height: 150,
                  decoration: BoxDecoration(
                    color: Colors.orange[100],
                    border: Border.all(color: Colors.orange, width: 2),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: const Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.broken_image, color: Colors.orange, size: 32),
                      SizedBox(height: 8),
                      Text(
                        'Error loading image',
                        style: TextStyle(fontSize: 10, color: Colors.orange),
                        textAlign: TextAlign.center,
                      ),
                    ],
                  ),
                ),
              ),
            ),

            const SizedBox(height: 32),
          ],
        ),
      ),
    );
  }

  Widget _buildSectionHeader(String title) {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
      decoration: BoxDecoration(
        color: Colors.deepPurple.withValues(alpha: 0.1),
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        title,
        style: const TextStyle(
          fontSize: 18,
          fontWeight: FontWeight.bold,
          color: Colors.deepPurple,
        ),
      ),
    );
  }

  Widget _buildTestCase(String title, Widget imageWidget) {
    return Column(
      children: [
        Text(
          title,
          style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
          textAlign: TextAlign.center,
        ),
        const SizedBox(height: 8),
        Card(
          elevation: 2,
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: imageWidget,
          ),
        ),
      ],
    );
  }
}
3
likes
160
points
219
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter package for handling network images, SVGs, local assets, file images, and memory images with caching and error handling.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

cached_network_image, flutter, flutter_svg

More

Packages that depend on image_builder