any_image_view 1.6.0 copy "any_image_view: ^1.6.0" to clipboard
any_image_view: ^1.6.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 with perfect scaling and custom placeholders
  • Lottie animations for engaging content (JSON/ZIP)
  • All image formats (PNG, JPG, JPEG, WebP, GIF, TIFF, RAW)
  • Asset images from your app bundle
  • Custom loading states with placeholders
  • Advanced error handling with custom widgets
  • Smooth animations with configurable fade duration
  • Network images with automatic caching and fade animations
  • Pinch-to-zoom and pan support for images.
  • Local files from your device (XFile & String paths)
  • 🛡️ 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),
),
),
),
],
)

🔧 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
errorPlaceHolder String? 'assets/images/not_found.png' Fallback image path
placeholderWidget Widget? null Custom loading widget
errorWidget Widget? null Custom error widget
fadeDuration Duration 400ms Fade animation duration

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 #

// Provide fallback images for better UX
AnyImageView(
imagePath: userAvatarUrl,
errorPlaceHolder: 'assets/images/default_avatar.png',
errorWidget: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey[300],
),
child: Icon(Icons.person),
),
)

🤝 Need Help? #


Made with ❤️ by Farhan Sadik Galib

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

72
likes
140
points
252
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