Flutter, Google's UI toolkit for building natively compiled applications, provides robust support for various image types and optimization techniques.
To add images to your Flutter project, follow these steps:
images
folder in your project root (or within the assets
folder)pubspec.yaml
file to include these assets:flutter:
assets:
- assets/images/
# Or list individual files
- assets/images/logo.png
- assets/images/background.jpg
After updating the pubspec.yaml
file, run flutter pub get
to update your project.
Flutter provides several widgets for displaying images:
The Image
widget is the primary way to display images in Flutter. It offers various constructors:
// Display image from assets
Image.asset('assets/images/logo.png')
// Display image from network
Image.network('https://example.com/image.jpg')
// Display image from file
Image.file(File('path o/file.png'))
// Display image from memory
Image.memory(bytes)
Here's a simple example of displaying an asset image:
import 'package:flutter/material.dart';
class ImageExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Image Example'),
),
body: Center(
child: Image.asset(
'assets/images/flutter_logo.png',
width: 200,
height: 200,
),
),
);
}
}
The Image widget offers many properties to control how images are displayed:
Image.asset(
'assets/images/photo.jpg',
width: 300, // Set width
height: 200, // Set height
fit: BoxFit.cover, // How image should be inscribed into the space
alignment: Alignment.center, // Alignment within the box
color: Colors.blue, // Apply color overlay
colorBlendMode: BlendMode.lighten, // Blend mode for color
filterQuality: FilterQuality.high, // Quality of image filtering
isAntiAlias: true, // Use anti-aliasing
repeat: ImageRepeat.noRepeat, // Repeat the image
)
The fit
property controls how the image should be inscribed into its container:
BoxFit.fill
: Stretch the image to fill the boxBoxFit.contain
: Ensure the entire image fits within the boxBoxFit.cover
: Fill the box, may crop the imageBoxFit.fitWidth
: Match the width of the boxBoxFit.fitHeight
: Match the height of the boxBoxFit.none
: Align the image within the box without scalingBoxFit.scaleDown
: Scale down to fit if needed, but never scale upFlutter supports resolution-appropriate images for different device pixel ratios, similar to Android's drawable resource directories:
assets/
images/
my_image.png // 1.0x (baseline)
1.5x/my_image.png // 1.5x resolution
2.0x/my_image.png // 2.0x resolution
3.0x/my_image.png // 3.0x resolution
4.0x/my_image.png // 4.0x resolution
In your code, you reference only the base asset:
Image.asset('assets/images/my_image.png')
Flutter automatically selects the appropriate asset based on the device's pixel ratio.
Loading images from the internet is straightforward with Image.network
:
Image.network(
'https://flutter.dev/images/flutter-logo-sharing.png',
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
),
);
},
errorBuilder: (context, error, stackTrace) {
return Text('Failed to load image');
},
)
Don't forget to add internet permission to your Android manifest:
<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">
<uses-permission android:name=\"android.permission.INTERNET\" />
<!-- Other content -->
</manifest>
For efficient network image caching, use the cached_network_image
package:
pubspec.yaml
:dependencies:
cached_network_image: ^3.3.0
import 'package:cached_network_image/cached_network_image.dart';
CachedNetworkImage(
imageUrl: 'https://example.com/image.jpg',
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
Creating a good user experience involves handling loading states properly:
// Using FadeInImage for smooth loading transition
FadeInImage.assetNetwork(
placeholder: 'assets/images/loading.gif',
image: 'https://example.com/image.jpg',
fadeInDuration: Duration(milliseconds: 700),
fadeOutDuration: Duration(milliseconds: 300),
)
// Or with memory placeholder
FadeInImage.memoryNetwork(
placeholder: kTransparentImage, // from 'package:transparent_image'
image: 'https://example.com/image.jpg',
)
To use SVG images, add the flutter_svg
package:
dependencies:
flutter_svg: ^2.0.8
Then use it in your code:
import 'package:flutter_svg/flutter_svg.dart';
SvgPicture.asset(
'assets/images/icon.svg',
width: 100,
height: 100,
)
Apply filters and effects to images:
ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.red,
BlendMode.modulate,
),
child: Image.asset('assets/images/photo.jpg'),
)
// Or use ImageFiltered widget for more effects
ImageFiltered(
imageFilter: ImageFilter.blur(
sigmaX: 5.0,
sigmaY: 5.0,
),
child: Image.asset('assets/images/photo.jpg'),
)
Create a custom image loading widget:
class CustomImage extends StatelessWidget {
final String url;
final double width;
final double height;
const CustomImage({
required this.url,
this.width = 100,
this.height = 100,
});
@override
Widget build(BuildContext context) {
return CachedNetworkImage(
imageUrl: url,
width: width,
height: height,
fit: BoxFit.cover,
placeholder: (context, url) => Container(
color: Colors.grey[300],
child: Center(
child: CircularProgressIndicator(),
),
),
errorWidget: (context, url, error) => Container(
color: Colors.grey[300],
child: Center(
child: Icon(Icons.error),
),
),
);
}
}