Flutter - Set Background Image

This tutorial shows you how to set a background image in Flutter.

A common way to set a background image in Flutter applications is by using DecorationImage. Below are the examples which include how to set the fit mode, transparency, and prevent image resizing when the keyboard is shown.

Set Background Image Using DecorationImage

You may already be familiar with Container widget. The constructor of Container has a parameter named decoration which is used to paint decoration behind the child. For that argument, you need to pass a Decoration value. There are some Decoration classes in Flutter. Some of them, such as BoxDecoration and ShapeDecoration, allow you to pass image argument whose type is DecorationImage Therefore, the idea is you need to create a Container and pass a Decoration that contains a DecorationImage. The other widgets that should be painted above the image have to be passed as the child argument of the Container (below the Container widget in the tree).

The DecorationImage constructor requires you to pass an argument whose name is also image, for which you need to pass an ImageProvider as the value. This tutorial uses NetworkImage as an example. But you can also use other ImageProviders such as MemoryImage, FileImage, or load an image from asset.

  static const String imageUrl = 'https://mocah.org/thumbs/268085-wallpaper-1080-2400.jpg';
  static const Widget appName = const Text(
    'Woolha.com',
    style: const TextStyle(color: Colors.white, fontSize: 48, fontWeight: FontWeight.bold),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Woolha.com Flutter Tutorial'),
      ),
      body: Container(
        width: double.infinity,
        height: double.infinity,
        decoration: BoxDecoration(
          image: DecorationImage(
            image: NetworkImage(imageUrl),
          ),
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            appName,
          ],
        ),
      ),
    );
  }

Output:

Flutter - Set Background Image - Decoration Image

Set Fit Mode

If the image doesn't fit on the screen, you may need to adjust how the image should be inscribed into the available space. It can be done by passing a BoxFit enum value as the fit argument. The possible values are:

  • 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(
        fit: BoxFit.fitWidth,
        image: NetworkImage(imageUrl),
      ),
    ),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        appName,
      ],
    ),
  ),

Output:

Flutter - Set Background Image - Decoration Image - Fit -  fitWidh

Set Image Transparency/Opacity

For setting the transparency or opacity of the background image, you can pass the colorFilter argument. In the example below, we create a ColorFilter with an opacity of 0.2. The blending mode is set to dstATop, which composite the destination image (the transparent filter) over the source image (the background image) where they overlap.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        fit: BoxFit.fitWidth,
        colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstATop),
        image: NetworkImage(imageUrl),
      ),
    ),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        appName,
      ],
    ),
  ),

Output:

Flutter - Set Background Image - Decoration Image - Opacity

Prevent Resizing when the Keyboard Is Shown

On mobile devices, an on-screen keyboard is usually displayed when the user is interacting with a text field. While the keyboard is shown, the screen area for the application content gets smaller. It can also affect how the background image is rendered since the image has to fit in a smaller space.

For example, there is a TextField widget

  static const Widget textField = const TextField(
    decoration: InputDecoration(
      labelText: 'Name',
      hintText: 'Enter your name',
      hintStyle: const TextStyle(color: Colors.white),
    )
  );

If the TextField widget is the current focus node, an on-screen keyboard will be displayed. As you can see in the output below, the background image is affected. In this case, because the fit mode is fitWidth, the image is pushed up to adjust with smaller available height space.

  Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        fit: BoxFit.fitWidth,
        image: NetworkImage(imageUrl),
      ),
    ),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        appName,
        textField,
      ],
    ),
  ),

Output:

Flutter - Set Background Image - Prevent Resize When Keybaord Is Shown

If you want to make the background image not affected by the presence of the keyboard, you can pass the resizeToAvoidBottomInset argument to the constructor of Scaffold and set the value to false. The value for that argument defaults to true, which causes the widgets to be resized so that they do not overlap the on-screen keyboard. 

  Scaffold(
    resizeToAvoidBottomInset: false,
    appBar: AppBar(
      title: const Text('Woolha.com Flutter Tutorial'),
    ),
    body: Container(
      width: double.infinity,
      height: double.infinity,
      decoration: BoxDecoration(
        image: DecorationImage(
          fit: BoxFit.fitWidth,\
          image: NetworkImage(imageUrl),\
        ),
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          appName,
          textField,
        ],
      ),
    ),
  )

Output:

Flutter - Set Background Image - Decoration Image - resizetoavoidbottominset - false

However, if the content doesn't fit into the available space, you will get another problem. As you can see on the output above, parts of content are not visible when the keyboard is shown. A possible workaround is wrapping the Scaffold inside a Container with a background image. Then, you need to put the content (which can be scrolled) under the Scaffold, wrapping it inside a SingleChildScrollView if necessary.

 return Container(
    width: double.infinity,
    height: double.infinity,
    decoration: BoxDecoration(
      image: DecorationImage(
        fit: BoxFit.fitWidth,
        image: NetworkImage(imageUrl),
      ),
    ),
    child: Scaffold(
      backgroundColor: Colors.transparent,
      // resizeToAvoidBottomInset: false,
      appBar: AppBar(
        title: const Text('Woolha.com Flutter Tutorial'),
      ),
      body: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            appName,
            appName,
            appName,
            textField,
            appName,
            appName,
            appName,
          ],
        ),
      ),
    ),
  );

Output:

Flutter - Set Background Image - Prevent Resize When Keybaord Is Shown

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: BackgroundImageExample(),
        debugShowCheckedModeBanner: false,
      );
    }
  }
  
  class BackgroundImageExample extends StatelessWidget {
  
    static const String imageUrl = 'https://mocah.org/thumbs/268085-wallpaper-1080-2400.jpg';
    static const Widget appName = const Text(
      'Woolha.com',
      style: const TextStyle(color: Colors.white, fontSize: 48, fontWeight: FontWeight.bold),
    );
    static const Widget textField = const TextField(
      decoration: InputDecoration(
        labelText: 'Name',
        hintText: 'Enter your name',
        hintStyle: const TextStyle(color: Colors.white),
      )
    );
  
    @override
    Widget build(BuildContext context) {
      // 1. Example without prevent image resizing (can be used if the application never show the on-screen keyboard).
      return Scaffold(
        resizeToAvoidBottomInset: false,
        appBar: AppBar(
          title: const Text('Woolha.com Flutter Tutorial'),
        ),
        body: Container(
          width: double.infinity,
          height: double.infinity,
          decoration: BoxDecoration(
            image: DecorationImage(
              fit: BoxFit.fitWidth,
              // colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstATop),
              image: NetworkImage(imageUrl),
              // image: Image.asset('assets/images/pikachu.png').image,
            ),
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              appName,
              textField,
            ],
          ),
        ),
      );
  
      // 2. Example that prevents image resizing when the keyboard is shown.
      return Container(
        width: double.infinity,
        height: double.infinity,
        decoration: BoxDecoration(
          image: DecorationImage(
            fit: BoxFit.fitWidth,
            // colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.dstATop),
            image: NetworkImage(imageUrl),
            // image: Image.asset('assets/images/pikachu.png').image,
          ),
        ),
        child: Scaffold(
          backgroundColor: Colors.transparent,
          // resizeToAvoidBottomInset: false,
          appBar: AppBar(
            title: const Text('Woolha.com Flutter Tutorial'),
          ),
          body: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                appName,
                appName,
                appName,
                textField,
                appName,
                appName,
                appName,
              ],
            ),
          ),
        ),
      );
    }
  }

Summary

To set a background image, you can use a Container widget and pass a Decoration object containing the image. For the image source, you need to create a DecorationImage and pass it to the Decoration. It's also possible to define how the image should be inscribed to the available space and set the opacity of the image. If the application contains a text field which may trigger the on-screen keyboard, you also need to handle that case as shown above. For other customizations you can read our tutorial about DecorationImage which explains how to set the alignment, repeat mode, center slice, and so on.