πŸ–ΌοΈ 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

Libraries

any_image_view