any_image_view 1.8.0 copy "any_image_view: ^1.8.0" to clipboard
any_image_view: ^1.8.0 copied to clipboard

A versatile Flutter image viewer supporting PNG, JPG, WebP, GIF, TIFF, RAW, SVG, Lottie, XFile, and cached network images — all in one seamless package.

🖼️ Any Image View #

Pub Version Pub Points Pub Likes License Flutter

Any Image View Demo

🎯 Why Choose Any Image View? #

Tired of juggling multiple image widgets? Say goodbye to complex image handling! This package gives you one widget that handles everything:

  • Network images with automatic caching and fade animations
  • Local files from your device (XFile & String paths)
  • SVG graphics (local assets) with perfect scaling and custom placeholders
  • Lottie animations (local assets) for engaging content (JSON/ZIP)
  • All image formats (PNG, JPG, JPEG, WebP, GIF, TIFF, RAW, HEIC, HEIF, BMP, ICO)
  • Asset images from your app bundle
  • Custom loading states with shimmer animation
  • Advanced error handling with built-in broken_image icon
  • Smooth animations with configurable fade duration
  • Pinch-to-zoom and pan support for images
  • Memory optimization for network images with cache control
  • HTTP headers support for authenticated network requests
  • 🛡️ Robust & Reliable - Comprehensive error handling and validation

No more headaches, just beautiful images!


Quick Start (30 seconds) #

1️⃣ Add to pubspec.yaml #

dependencies:
  any_image_view: ^1.6.0

2️⃣ Run this command #

flutter pub get

3️⃣ Copy & Paste this code #

import 'package:any_image_view/any_image_view.dart';

// Replace your existing Image widgets with this:
AnyImageView(
imagePath: 'https://picsum.photos/300/200',
height: 200,
width: 300,
borderRadius: BorderRadius.circular(12),
onTap: () => print('Image tapped!'),
)

That's it! You're ready to go! 🎉


📱 Profile Pictures #

AnyImageView(
imagePath: user.profileImageUrl,
height: 80,
width: 80,
shape: BoxShape.circle,
border: Border.all(color: Colors.blue, width: 2),
onTap: () => _showProfileDetails(),
)
AnyImageView(
imagePath: galleryItem.url,
height: 200,
width: double.infinity,
boxFit: BoxFit.cover,
borderRadius: BorderRadius.circular(8),
placeholderWidget: Center(
child: CircularProgressIndicator(),
),
errorWidget: Center(
child: Icon(Icons.error, color: Colors.red),
),
)

🎨 SVG Icons & Logos #

AnyImageView(
imagePath: 'assets/icons/app_logo.svg',
height: 40,
width: 40,
fit: BoxFit.contain,
placeholderWidget: SizedBox(
height: 40,
width: 40,
child: LinearProgressIndicator(),
),
)

🎬 Lottie Animations #

AnyImageView(
imagePath: 'assets/animations/loading.json',
height: 100,
width: 100,
fit: BoxFit.contain,
)

📸 XFile from Image Picker #

AnyImageView(
imagePath: pickedFile, // XFile object
height: 250,
width: 250,
borderRadius: BorderRadius.circular(15),
fadeDuration: Duration(milliseconds: 300),
)

📸 Complete Image Picker Integration #

Want to let users pick images? Here's the complete solution:

import 'package:image_picker/image_picker.dart';
import 'package:any_image_view/any_image_view.dart';

class ImagePickerScreen extends StatefulWidget {
  @override
  _ImagePickerScreenState createState() => _ImagePickerScreenState();
}

class _ImagePickerScreenState extends State<ImagePickerScreen> {
  XFile? selectedImage;

  Future<void> pickImage() async {
    final ImagePicker picker = ImagePicker();
    final XFile? image = await picker.pickImage(source: ImageSource.gallery);

    setState(() {
      selectedImage = image;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          ElevatedButton(
            onPressed: pickImage,
            child: Text('📷 Pick Image'),
          ),
          SizedBox(height: 20),
          if (selectedImage != null)
            AnyImageView(
              imagePath: selectedImage,
              height: 250,
              width: 250,
              borderRadius: BorderRadius.circular(15),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.2),
                  blurRadius: 10,
                  offset: Offset(0, 5),
                ),
              ],
              fadeDuration: Duration(milliseconds: 500),
              onTap: () => print('Selected image tapped!'),
            ),
        ],
      ),
    );
  }
}

🎨 Advanced Styling Examples #

Card-Style Image with Custom Loading #

AnyImageView(
imagePath: 'https://example.com/image.jpg',
height: 200,
width: double.infinity,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: Offset(0, 4),
),
],
margin: EdgeInsets.all(16),
placeholderWidget: Container(
height: 200,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(16),
),
child: Center(
child: CircularProgressIndicator(),
),
),
onTap: () => _openImageDetails(),
)

Circular Avatar with Error Handling #

AnyImageView(
imagePath: user.avatarUrl,
height: 60,
width: 60,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 3),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 6,
offset: Offset(0, 2),
),
],
errorWidget: Container(
height: 60,
width: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey[300],
),
child: Icon(Icons.person, color: Colors.grey[600]),
),
)

Hero Image with Gradient Overlay #

Stack(
children: [
AnyImageView(
imagePath: 'assets/images/hero.jpg',
height: 300,
width: double.infinity,
fit: BoxFit.cover,
fadeDuration: Duration(milliseconds: 800),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.transparent, Colors.black.withOpacity(0.7)],
),
),
padding: EdgeInsets.all(16),
child: Text(
'Beautiful Hero Image',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
),
],
)

🚀 Advanced Network Image Features #

Smart Caching & Memory Optimization #

Improved cached_network_image implementation with advanced features:

AnyImageView(
  imagePath: 'https://example.com/large-image.jpg',
  height: 300,  // Automatically used for memory cache optimization
  width: 300,   // Automatically used for memory cache optimization
  
  // Custom HTTP headers for authenticated requests
  httpHeaders: {
    'Authorization': 'Bearer your_token_here',
    'Custom-Header': 'custom_value',
  },
  
  // Advanced caching control
  useMemoryCache: true, // Enable in-memory caching
  cacheMaxAge: Duration(days: 7), // Cache duration
  maxRetryAttempts: 3, // Retry failed requests
  
  // Enhanced error handling
  errorWidget: Container(
    color: Colors.grey[200],
    child: Icon(Icons.error),
  ),
)

Authenticated Network Images #

// Load images with authentication headers
AnyImageView(
  imagePath: 'https://api.example.com/user/avatar.jpg',
  httpHeaders: {
    'Authorization': 'Bearer ${authToken}',
    'X-API-Key': apiKey,
  },
  height: 100,
  width: 100,
  shape: BoxShape.circle,
)

Memory-Efficient Large Images #

// Optimize memory for high-resolution images
// The widget automatically uses height/width for memory cache optimization
AnyImageView(
  imagePath: 'https://example.com/4k-image.jpg',
  height: 200,  // Used for memory cache
  width: 300,   // Used for memory cache
  fit: BoxFit.cover,
)

Retry Logic for Poor Networks #

// Automatically retry failed network requests
AnyImageView(
  imagePath: 'https://slow-server.com/image.jpg',
  maxRetryAttempts: 5, // Retry up to 5 times
  placeholderWidget: CircularProgressIndicator(),
  errorWidget: Text('Failed to load after retries'),
)

🔧 Complete API Reference #

Constructor Parameters #

Parameter Type Default Description
imagePath Object? null String path/URL or XFile object
height double? null Image container height
width double? null Image container width
fit BoxFit? BoxFit.cover How image fits in container
alignment Alignment? null Image alignment within container
borderRadius BorderRadius? null Rounded corners
shape BoxShape BoxShape.rectangle Rectangle or circle
border BoxBorder? null Border styling
boxShadow List<BoxShadow>? null Shadow effects
margin EdgeInsetsGeometry? null Outer spacing
padding EdgeInsetsGeometry? null Inner spacing
onTap VoidCallback? null Tap callback function
placeholderWidget Widget? null Custom loading widget
errorWidget Widget? null Custom error widget (defaults to broken_image icon)
fadeDuration Duration 400ms Fade animation duration
enableZoom bool false Enable pinch-to-zoom functionality
httpHeaders Map<String, String>? null Custom HTTP headers for network images
cacheMaxAge Duration? null Maximum cache duration for network images
maxRetryAttempts int 3 Max retry attempts for failed requests
useMemoryCache bool true Enable in-memory caching (uses height/width for cache dimensions)

Supported Image Formats #

Format Extension Description Example
PNG .png Portable Network Graphics 'assets/images/logo.png'
JPG/JPEG .jpg, .jpeg Joint Photographic Experts Group 'assets/photos/image.jpg'
WebP .webp Web Picture format 'assets/images/photo.webp'
GIF .gif Graphics Interchange Format 'assets/animations/loading.gif'
TIFF .tiff Tagged Image File Format 'assets/images/document.tiff'
RAW .raw Raw image format 'assets/images/photo.raw'
SVG .svg Scalable Vector Graphics 'assets/icons/icon.svg'
Lottie .json, .zip Lottie animations 'assets/animations/animation.json'
Network http://, https:// HTTP/HTTPS URLs 'https://example.com/image.jpg'
XFile XFile object Cross-platform file objects pickedFile

🛡️ Advanced Error Handling #

Custom Error Widget #

AnyImageView(
imagePath: 'https://broken-link.com/image.jpg',
height: 200,
width: 200,
errorWidget: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(8),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.error_outline, size: 48, color: Colors.red),
SizedBox(height: 8),
Text('Image not available', style: TextStyle(color: Colors.grey[600])),
],
),
),
)

Custom Loading Widget #

AnyImageView(
imagePath: 'https://slow-server.com/large-image.jpg',
height: 300,
width: 300,
placeholderWidget: Container(
height: 300,
width: 300,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.grey[300]!, Colors.grey[200]!],
),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 8),
Text('Loading...', style: TextStyle(color: Colors.grey[600])),
],
),
),
),
)

Smooth Fade Animations #

AnyImageView(
imagePath: 'https://example.com/image.jpg',
height: 200,
width: 200,
fadeDuration: Duration(milliseconds: 800), // Custom fade duration
onTap: () => print('Image with smooth fade animation'),
)

📱 Platform Support #

Platform Status Features
Android ✅ Perfect All formats & features supported
iOS ✅ Perfect All formats & features supported
Web ✅ Perfect All formats & features supported
macOS ✅ Perfect All formats & features supported
Windows ✅ Perfect All formats & features supported
Linux ✅ Perfect All formats & features supported

🔄 Migration Guide #

Before (Multiple widgets needed): #

// Network images
CachedNetworkImage(
imageUrl: imageUrl,
height: 200,
width: 200,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)

// Local files
Image.file(
File(filePath),
height: 200,
width: 200,
errorBuilder: (context, error, stackTrace) => Icon(Icons.error),
)

// SVG files
SvgPicture.asset(
'assets/icon.svg',
height: 200,
width: 200,
placeholderBuilder: (context) => CircularProgressIndicator(),
)

After (One widget for all): #

// All image types with one widget!
AnyImageView(
imagePath: imageUrl, // or filePath, or asset path, or XFile
height: 200,
width: 200,
placeholderWidget: CircularProgressIndicator(),
errorWidget: Icon(Icons.error),
)

🎯 Pro Tips & Best Practices #

1. Performance Optimization #

// Always specify dimensions for better performance
AnyImageView(
imagePath: imageUrl,
height: 200,
width: 200, // Specific dimensions improve performance
fit: BoxFit.cover,
)

2. Memory Management #

// Use appropriate placeholder sizes for large galleries
AnyImageView(
imagePath: imageUrl,
placeholderWidget: SizedBox(
height: 30,
width: 30,
child: CircularProgressIndicator(strokeWidth: 2),
),
)

3. Accessibility #

// Add semantic labels for screen readers
AnyImageView(
imagePath: imageUrl,
onTap: () => _handleTap(),
).semanticsLabel('User profile picture'),
)

4. Custom Animations #

// Use longer fade duration for hero images
AnyImageView(
imagePath: heroImageUrl,
fadeDuration: Duration(milliseconds: 1000), // Smooth transition
)

5. Error Recovery #

// Default broken_image icon is shown automatically on error
AnyImageView(
imagePath: userAvatarUrl,
height: 100,
width: 100,
shape: BoxShape.circle,
)

// Or provide a custom error widget for better UX
AnyImageView(
imagePath: userAvatarUrl,
errorWidget: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey[300],
),
child: Icon(Icons.person, size: 40),
),
)

🤝 Need Help? #


Made with ❤️ by Farhan Sadik Galib

If this package helps you, please consider giving it a ⭐ on Pub.dev

80
likes
160
points
497
downloads
screenshot

Publisher

verified publisherfarhansadikgalib.com

Weekly Downloads

A versatile Flutter image viewer supporting PNG, JPG, WebP, GIF, TIFF, RAW, SVG, Lottie, XFile, and cached network images — all in one seamless package.

Homepage
Repository (GitHub)
View/report issues

Topics

#flutter #image #image-viewer #svg #lottie

Documentation

API reference

License

MIT (license)

Dependencies

cached_network_image, cross_file, flutter, flutter_svg, lottie

More

Packages that depend on any_image_view