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 ImageProvider
s 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:
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:
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:
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:
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:
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:
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.