๐Ÿ–ผ๏ธ Any Image View

Pub Version License

Any Image View

One widget for all image types โ€” Network, Assets, SVG, Lottie, XFile with built-in shimmer loading & error handling.

Installation

dependencies:
  any_image_view: ^2.3.1

Android NDK version

This package depends on native plugins (the jni library, pulled in transitively via path_provider) that require the NDK shipped with your Flutter SDK. Apps created with an older Flutter template may omit the ndkVersion line and show this warning on every Android build:

Your project is configured with Android NDK <x>, but the following plugin(s)
depend on a different Android NDK version:
- jni requires Android NDK 28.2.13676358

Recent flutter create templates already include the fix below, so most apps never see this. If yours does, add this one line to android/app/build.gradle.kts:

android {
    ndkVersion = flutter.ndkVersion
    // ...
}

(or ndkVersion = flutter.ndkVersion in android/app/build.gradle for the Groovy DSL).

Using flutter.ndkVersion rather than a hardcoded value means it always tracks your own Flutter SDK โ€” it never goes stale and pins no dependency, so it won't conflict with other packages.

Android build fails: Redeclaration: class FlutterAvifPlugin

If your Android build fails with:

e: .../flutter_avif_android-3.1.0/.../FlutterAvifPlugin.kt:12:7 Redeclaration:
class FlutterAvifPlugin : FlutterPlugin, MethodChannel.MethodCallHandler
class FlutterAvifPlugin : Any, FlutterPlugin, MethodChannel.MethodCallHandler

> Execution failed for task ':flutter_avif_android:compileDebugKotlin'.

this is an upstream packaging bug in flutter_avif_android (3.1.0, the current release), not in this package. That plugin ships the same class twice โ€” once as src/main/java/.../FlutterAvifPlugin.java and once as src/main/kotlin/.../FlutterAvifPlugin.kt โ€” and both declare com.teknorota.flutter_avif.FlutterAvifPlugin.

Older AGP silently ignored the stray Java file. AGP 8.9+ compiles both source sets, so the two declarations collide. Nothing you wrote is wrong, and no version of any_image_view can avoid it, because the duplicate lives inside the transitive plugin.

Until upstream removes the duplicate file, add this to your app-level android/build.gradle.kts (the root one, next to settings.gradle.kts โ€” not app/build.gradle.kts):

subprojects {
    if (project.name == "flutter_avif_android") {
        project.plugins.withId("com.android.library") {
            project.extensions.configure<com.android.build.gradle.LibraryExtension>("android") {
                sourceSets.getByName("main") {
                    java.setSrcDirs(listOf("src/main/kotlin"))
                }
            }
        }
    }
}

For the Groovy DSL (android/build.gradle):

subprojects {
    if (project.name == 'flutter_avif_android') {
        project.plugins.withId('com.android.library') {
            project.android.sourceSets.main.java.srcDirs = ['src/main/kotlin']
        }
    }
}

This keeps the Kotlin class (the one pluginClass: actually registers) and drops the redundant Java copy. It is behaviour-preserving: both classes are identical getPlatformVersion stubs, and no AVIF decoding goes through them โ€” that runs through the plugin's native Rust library. Remove the block once flutter_avif_android ships without the duplicate file.

A working reference copy lives in this repo at example/android/build.gradle.kts.

Usage

import 'package:any_image_view/any_image_view.dart';

// Network
AnyImageView(imagePath: 'https://example.com/image.jpg', height: 200, width: 200)

// Asset
AnyImageView(imagePath: 'assets/image.png', height: 200, width: 200)

// SVG (asset or network)
AnyImageView(imagePath: 'assets/icon.svg', height: 40, width: 40)
AnyImageView(imagePath: 'https://example.com/icon.svg', height: 40, width: 40, svgColor: Colors.blue)

// Lottie
AnyImageView(imagePath: 'assets/animation.json', height: 100, width: 100)

// AVIF (asset, network, or file โ€” animated AVIFs auto-play)
AnyImageView(imagePath: 'assets/photo.avif', height: 200, width: 200)
AnyImageView(imagePath: 'https://example.com/photo.avif', height: 200, width: 200)

// XFile (Image Picker)
AnyImageView(imagePath: xFile, height: 200, width: 200)

// Circular Avatar
AnyImageView(imagePath: url, height: 80, width: 80, shape: BoxShape.circle)

// With Options
AnyImageView(
  imagePath: url,
  height: 200,
  width: 200,
  fit: BoxFit.cover,
  borderRadius: BorderRadius.circular(12),
  enableZoom: true,
  placeholderWidget: CircularProgressIndicator(),
  errorWidget: Icon(Icons.error),
)

Parameters

Parameter Type Description
imagePath Object? URL, asset path, or XFile
height / width double? Dimensions
fit BoxFit? Image fit (default: cover)
shape BoxShape rectangle or circle
borderRadius BorderRadius? Rounded corners
enableZoom bool Pinch-to-zoom (default: false)
placeholderWidget Widget? Custom loader
errorWidget Widget? Custom error
httpHeaders Map? Auth headers for network/SVG
svgColor Color? Tint color for SVG (asset & network)
svgColorFilter ColorFilter? Custom color filter for SVG

Supported Formats

PNG, JPG, WebP, GIF, AVIF, SVG, Lottie (.json), TIFF, RAW, HEIC, BMP, ICO

Platform Support

โœ… Android ยท โœ… iOS ยท โœ… Web ยท โœ… macOS ยท โœ… Windows ยท โœ… Linux


Libraries

any_image_view
A versatile Flutter image viewer supporting multiple image formats.