Flutter - Using DecorationImage Examples

This tutorial shows you how to use DecorationImage in Flutter.

Certain Decoration classes in Flutter allow you to pass an image to use as a decoration. The image needs to be defined as a DecorationImage. It's quite common to use a DecorationImage for setting a background image. Not only defining the image to use, you can also adjust how the image should be painted. Below are the examples of how to use DecorationImage.

Using DecorationImage

A DecorationImage instance can be passed as the image argument of BoxDecoration or ShapeDecoration. To create the instance, you need to call the constructor below.

  const DecorationImage({
    required ImageProvider<Object> image,
    ImageErrorListener? onError,
    ColorFilter? colorFilter,
    BoxFit? fit,
    AlignmentGeometry alignment = Alignment.center,
    Rect? centerSlice,
    ImageRepeat repeat = ImageRepeat.noRepeat,
    bool matchTextDirection = false,
    double scale = 1.0,
  })

The only required argument is image, for which you need to pass an imageProvider. The other arguments are optional and can be used to adjust how the image should be rendered, such as setting the alignment, adding color filter, scaling the image, and so on.

Set Image

You need to pass an ImageProvider which contains the image to use as a decoration as the image argument. ImageProvider itself is an abstract class for resolving an image based on the environment. There are some classes that extend ImageProvider which includes:

The differences between them are the resource type of the image. The examples in this tutorial only use NetworkImage. You can click the above links which explain how to load an image using the respective ImageProvider.

To load an image from network using NetworkImage, pass the image URL as the argument of NetworkImage. Then, pass the NetworkImage as the image argument of DecorationImage. Below is the URL of the image used in this tutorial.

  static const String _imageUrl = 'https://www.pixel4k.com/preview.php?src=https://www.pixel4k.com/wp-content/uploads/2018/10/sun-in-clouds-sea-nature-4k_1540139445.jpg&w=240&h=320';

Here's a basic example that only passes the required argument (image). It uses NetworkImage as the ImageProvider.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

Output:

Flutter - DecorationImage - Image

Set Color Filter

You can set the color filter to be applied to the image by passing a ColorFilter as the colorFilter argument. You can create a ColorFilter using one of its named constructor: mode, matrix, linearToSrgbGamma, and srgbToLinearGamma. Our tutorial about ColorFiltered widget explains how to use those named constructors.

Below is an example of a ColorFilter that gives a transparent effect to the image.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
        colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstATop),
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

Output:

Flutter - DecorationImage - Color Filter

Set Fit Mode

Sometimes the resource image doesn't have the same size or aspect ratio as the target box. In that case, you may need to adjust how the image should be sized based on the available space. It can be done by passing the fit argument whose type is BoxFit enum. Below is the list of the enum values that can be used to set the fit mode.

  • fill: Set the source to fill the target box. It may distort the aspect ratio of the source.
  • contain: Set the source to be as large as possible within the target box.
  • cover: Set the source to be as small as possible while still covering the entire target box..
  • fitWidth: Set the source's width to match the target box's width. It may cause the source to overflow the target box vertically.
  • fitHeight: Set the source's height to match the target box's width. It may cause the source to overflow the target box horizontally.
  • none: Align the source within the target box and discard any portion outside the box..
  • scaleDown: Align the source within the target box and scale down the source to fit the target box if necessary.
  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
        fit: BoxFit.fitWidth,
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

Output:

Flutter - DecorationImage - Color Filter

Set Alignment

The alignment of the image inside the target box can be set using the alignment argument. The argument is optional. If you don't pass it, it defaults to center. The passed value is an AlignmentGeometry which can be obtained using the constructor or a static constant of Alignment.

The code below sets the alignment to bottomLeft.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
        alignment: Alignment.bottomLeft,
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

Output:

Flutter - DecorationImage - Alignment - bottomLeft

Set Repeat Mode

If the image doesn't fill the entire space, by default it will leave empty space where the image is not painted. If you want to repeat the image to fill the empty space, you can pass the repeat argument with a ImageRepeat enum as the value. The enum values are:

  • repeat: Repeat the image in both the x and y directions until the box is filled.
  • repeatX: Repeat the image in the x direction until the box is filled horizontally.
  • repeatY: Repeat the image in the y direction until the box is filled vertically.
  • noRepeat: Leave uncovered portions of the box transparent..

Since the default value is noRepeat, the image is not repeated by default. The example below uses repeat mode which causes the image to be repeated until the box is filled.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
        repeat: ImageRepeat.repeat,
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

Output:

Flutter - DecorationImage - Repeat - repeat

Set Scale

The scale argument can be used to set how many image pixels to be shown per logical pixels. The value defaults to 1. If the value is increased to 2, there will be two image pixels per logical pixels. Hence, the image width and height are two times smaller than the original size. However, the fit mode may affect the scale. For example, if you use BoxFit.fill, the image will always be resized to fill the entire space and the scale doesn't affect the size of the image.

To make it more obvious, the two examples below use BoxFit.none passed as the fit argument. The code below sets the scale argument to 2. As a result, the image is twice as small as the original image.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
        scale: 2,
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

Output:

Flutter - DecorationImage - Scale - 2

In the next example, the value of the scale argument is 0.5. Since an image pixel is rendered in 2 x 2 logical pixels, the rendered image is twice as big as the original image.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
        scale: 0.5,
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

Output:

Flutter - DecorationImage - Scale - 0.5

Match Text Direction

A widget subtree in Flutter has a default text direction. By default, the image doesn't follow the text direction and is always drawn in the normal painting direction. If you want to make the painting direction always equal to the text direction, you can set the matchTextDirection argument to false (defaults to true).

  Directionality(
    textDirection: TextDirection.rtl,
    child: Container(
      width: double.infinity,
      height: double.infinity,
      decoration: BoxDecoration(
        image: DecorationImage(
          image: NetworkImage(_imageUrl),
          matchTextDirection: true,
        ),
      ),
      child: Center(
        child: _appName,
      ),
    ),
  )

Output:

Flutter - DecorationImage - Match Text Direction

Set Center Slice

DecorationImage allows you to define a center slice, which can be used to determine how an image should be stretched to fit the target box. Part of the image inside the center slice will be stretched both horizontally and vertically. Part of the image above and below the center slice will be stretched horizontally, while part of the image on the left and right of the center slice will be stretched vertically.

To define a center slice, you need to pass a rectangle (Rect) to be used as the center slice as the centerSlice argument. If the centerSlice argument is not null, the fit value defaults to fill.

You're not allowed to pass cover or none as the fit argument value. Breaking the rule will throw the below exception.

  ======== Exception caught by rendering library =====================================================
  The following assertion was thrown during paint():
  'package:flutter/src/painting/decoration_image.dart': Failed assertion: line 456 pos 10: 'centerSlice == null || (fit != BoxFit.none && fit != BoxFit.cover)': is not true.

It's also not allowed to use a BoxFit that does not guarantee that the image is fully visible. That means you cannot use fitWidth or fitHeight. In addition, the width and height constraints applied to the box must not be smaller than the rendered image's width and height respectively if the CenterSlice. Below is the exception if you use unsupported fit mode or smaller image size.

  ======== Exception caught by rendering library =====================================================
  The following assertion was thrown during paint():
  centerSlice was used with a BoxFit that does not guarantee that the image is fully visible.
  'package:flutter/src/painting/decoration_image.dart':
  Failed assertion: line 465 pos 12: 'sourceSize == inputSize'

Below is an example of how to use CenterSlice.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
        centerSlice: Rect.fromCenter(center: Offset(200, 200), width: 1, height: 1),
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

Output:

Flutter - DecorationImage - Center Slice

Handle Error

An exception will be thrown when an error occurs while the image is being loaded. For example, if the image resource doesn't exist or has invalid format. To catch the error, you can add a callback function as the onError argument. The function has two parameters of types Object and StackTrace, with the latter is optional.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        image: NetworkImage(_imageUrl),
        onError: (Object exception, StackTrace? stackTrace) {
          print('onError');
          print('Exception: $exception');
          print('Stack Trace:\n$stackTrace');
        },
      ),
    ),
    child: Center(
      child: _appName,
    ),
  )

DecorationImage - Parameters

  • required ImageProvider<Object> image: The image to be painted into the decoration.
  • ImageErrorListener? onError: Error callback to be called every time an error occurs while loading the image.
  • ColorFilter? colorFilter: The color filter to apply to the image.
  • BoxFit? fit: How the image should be inscribed into the box.
  • AlignmentGeometry alignment: How to align the image within its bounds. Defaults to Alignment.center.
  • Rect? centerSlice: The center slice used to control how an image should be stretched to fill the entire space.
  • ImageRepeat repeat: How to paint any portions of the box that would not otherwise be covered by the image. Defaults to ImageRepeat.noRepeat.
  • bool matchTextDirection: Whether to paint the image in the direction of the TextDirection. Defaults to false.
  • double scale: The image pixels to be shown per logical pixels. Defaults to 1.0.

?: value can be null.
required: value must be passed.

Full Code

  import 'package:flutter/material.dart';
  
  void main() => runApp(MyApp());
  
  class MyApp extends StatelessWidget {
  
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Woolha.com Flutter Tutorial',
        home: DecorationImageExample(),
        debugShowCheckedModeBanner: false,
      );
    }
  }
  
  class DecorationImageExample extends StatelessWidget {
  
    static const String _imageUrl = 'https://www.pixel4k.com/preview.php?src=https://www.pixel4k.com/wp-content/uploads/2018/10/sun-in-clouds-sea-nature-4k_1540139445.jpg&w=240&h=320';
    static const Widget _appName = const Text(
      'Woolha.com',
      style: const TextStyle(color: Colors.teal, fontSize: 48, fontWeight: FontWeight.bold),
    );
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        resizeToAvoidBottomInset: false,
        appBar: AppBar(
          title: const Text('Woolha.com Flutter Tutorial'),
        ),
        body: Directionality(
          textDirection: TextDirection.rtl,
          child: Container(
            width: double.infinity,
            height: double.infinity,
            decoration: BoxDecoration(
              image: DecorationImage(
                image: NetworkImage(_imageUrl),
                colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstATop),
                // fit: BoxFit.fitWidth,
                alignment: Alignment.bottomLeft,
                repeat: ImageRepeat.repeat,
                scale: 2,
                matchTextDirection: true,
                centerSlice: Rect.fromCenter(center: Offset(200, 200), width: 1, height: 1),
                onError: (Object exception, StackTrace? stackTrace) {
                  print('onError');
                  print('Exception: $exception');
                  print('Stack Trace:\n$stackTrace');
                },
              ),
            ),
            child: Center(
              child: _appName,
            ),
          ),
        ),
      );
    }
  }

Summary

That's how to create a DecorationImage. You have to pass an ImageProvider when calling the constructor of DecorationImage. You can also pass other optional arguments to customize how the image should be rendered. Finally, pass it as the image argument of a BoxDecoration or a ShapeDecoration.