Widgets 03 | Image

In this article, I will tell you more detail about the widget Image.

Before Start

The Image widget show the picture to rich our message. It is so basic widget that we must know how to use it. This step, we will create a page to show our all tutorial contents. Just look at the code below, we will add our widgets inside the children.

import "package:flutter/material.dart";
import 'package:flutter_widgets/const/_const.dart';

class ImagePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ImageState();
}
class _ImageState extends State<ImagePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(PageName.IMAGE),
      ),
      body: SingleChildScrollView(
          child: Column(
        children: <Widget>[
        //we will add our widgets here.
        ],
      )),
    );
  }
}

It will show you like follows, it contains nothing, just the title.

Simple Use

If you are a beginner, you should know how to use the image for the first time. So we should prepare the pictures that we can use. I have prepared them for you as follows.

Then create a folder in our project and put our pictures inside it. I create assets,images,image folders as a path assets/images/image.

Then, configure the pubspec.yaml file in our project. Like this.

flutter:
  assets:
    - assets/images/
    - assets/images/image/

You should know you can configure one file like - assets/images/image/pic01.png, but if you want to configure the all file in a folder, you should configure it like I do.

You should care about that if the a folder have a child folder, you should configure the child folder again to be valid. Like the child folder image in the images . Otherwise it will be invalid.

Finally, we can use them, just put the name as the param will show the picture.

   Image.asset("assets/images/image/pic02.png")

The name of the picture should contain the whole path like above, do not use like pic02.png. In order to show our picture smaller, I have some handles.

 Container(
            constraints: BoxConstraints.expand(height: 300),
            alignment: Alignment.center,
            child: Image.asset(
              "assets/images/image/pic02.png",
              fit: BoxFit.cover,
            ),
          )

Then our simple use of the picture is done. So let's travel with our high-level tutorial below.

Constructor

In our every fore tutorial, I always tell you that if you want to use some widgets, you should look at the constructor at the first time, then you can go fast. So let's go!

Image.asset(String name, {
    Key key,
    AssetBundle bundle,
    this.semanticLabel,
    this.excludeFromSemantics = false,
    double scale,
    this.width,
    this.height,
    this.color,
    this.colorBlendMode,
    this.fit,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.centerSlice,
    this.matchTextDirection = false,
    this.gaplessPlayback = false,
    String package,
    this.filterQuality = FilterQuality.low,
  })

Image has several constructors,such as Image({...}),Image.network(src,{...}),Image.file(file,{...}) ,Image.memory(bytes, {...})their main different is from their source, but most parameters are same. Because of our article focus on widget, I will tell you for the next topic.

width & height

These two parameters control the size of the size. The type is double, the example is below.

  Widget _limitSize() => Container(
        color: RED,
        child: Image.asset(
          _PIC01,
          height: 100,
          width: 100,
        ),
      );

We create make a function to show it and put a Container to contain it. You have noticed that the name of _PIC01, I define them upon the class just in the same file, it doesn't mater if you don't do as this, but this is very convenience to use.

const _PATH = "assets/images/image";
const _PIC01 = "$_PATH/pic01.png";
const _PIC02 = "$_PATH/pic02.png";
const _PIC03 = "$_PATH/pic03.png";
const _PIC04 = "$_PATH/pic04.png";
const _PIC05 = "$_PATH/pic05.png";
const _PIC06 = "$_PATH/pic06.png";
const _PIC07 = "$_PATH/pic07.png";
const _PIC08 = "$_PATH/pic08.png";
const _PIC09 = "$_PATH/pic09.png";
const _PIC10 = "$_PATH/pic10.png";
const _PIC11 = "$_PATH/pic11.png";
const _CIRCLE = "$_PATH/circle_10.png";

Then call the function _limitSize() in our children property. In the follow parameter I will tell you, I don't tell you as the detail of the using function as this example, I just tell the main function we use, the other description will ignore.

  SizedBox(
        height: 10,
          ),
  Text(
        "width = 100, height = 100",
        style: TextStyle(color: RED),
          ),
 _limitSize(),

fit

The param control how does the picture show in Image. When we look at the definition, it extends the BoxFit.

final BoxFit fit;

The BoxFit is a enum in the flutter. So we use it just as type.

enum BoxFit {  fill,contain,cover,fitWidth,fitHeight, none,scaleDown,}

1. fill

So what means about these parameters, we assume we have a Container with width equal 100 and height equal 100. The fill means that the picture will stretch the width and the height to 100, then the ratio of the picture will may be changed.It often looked as abnormal.

 Widget _fillImage() => Container(
        child: Image.asset(
          _PIC01,
          width: 100,
          height: 100,
          fit: BoxFit.fill,
        ),
      );

It will show like below, we compare with the above one, we can see the ratio of the picture is changed, but it cover all of its parent widget.

2. fitWidth & fitHeight

These three parameters are similar at some way, so I put them together. Also we assume the width equal 100 and height equal 100 of the parent widget Container.

First, we talk about the fitWidth, if we set this, the picture will set the width equal to 100, and then stretch the height with the same stretch ratio. The size of the pic01.png is 720*1202. if we stretch the width equal 100, then the ratio s = 100/720, so the height of the picture should be h=1202*s=1202*100/720 =167 , but our height of our Container is 100, don't completely show the picture, so the Image will don't the other part of the picture. But which part? This depends on the parameter of the alignment, but default we show the picture in the center, then it will cut up and down symmetry part.

  Widget _fitContain() => Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Container(
            color: YELLOW,
            width: 100,
            height: 100,
            child: Image.asset(
              _PIC01,
              fit: BoxFit.fitWidth,
            ),
          )
        ],
      );

Also, the fitHeight is the same as the fitWidth, but this time we need to stretch with height first, then stretch with the same ratio for the width, then cut the horizontal direction if it is larger than the parent widget. Finally, we will get the result as we want. See code below, we just add code in function _fitContain.

Container(
            color: YELLOW,
            width: 100,
            height: 100,
            child: Image.asset(
              _PIC01,
              fit: BoxFit.fitHeight,
            ),

3. contain

We know about the fitWidth and fitHeight now. Then we can look at the contain, What can we get it. Just watch our example carefully, you can see the different between the fitWidth Image and the fitHeight Image. The fore one full cover the container,but not show the entire picture to you. the latter one not cover the whole Container, but show the entire picture. So it depends on the result of the stretch size. If the result is larger than parent widget,Then it will show like the first-one, otherwise it will show you like the second-one. So I will tell you what contain may do.

  1. Stretch the width like the fitWidth parameter, we get the result-one.

  2. Stretch the height like the fitHeight parameter, we get the result-two.

  3. Select one who show the entire picture.In above example,we will select fitHeightone.

The principle just help us to understand, don't the represent that the contain really do. We can have a short note about the contain, contain = entire-picture(fitWidth,fitHeight) , hope you like this, we just change to contain to see the result.

 Container(
            color: RED,
            width: 100,
            height: 100,
            child: Image.asset(
              _PIC01,
              fit: BoxFit.contain,
            ),
          ),

4. cover

It is very interest that we also explain the cover with the fitWidth and the fitHeight. You can understand the cover parameter as follow step.

  1. Stretch the width like the fitWidth parameter, we get the result-one.

  2. Stretch the height like the fitHeight parameter, we get the result-two.

  3. Select one who cover the whole parent widget.In above example,we should select fitWidthone.

These principles are very similar with the containin fore two steps, but in the last step, contain select the one who show the entire picture, while cover select the one who cover the whole parent widget. It is a bit different, but sometime they same when the Image show the entire picture and also cover the whole parent widget.

Widget _fitCover() => Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          Container(
            color: YELLOW,
            width: 100,
            height: 100,
            child: Image.asset(
              _PIC01,
              fit: BoxFit.cover,
            ),
          ),
        ],
      );

You can see, it is the same as the fitWidth one.

5. scaleDown & none

When the parent widget has not enough to show our picture, then we should scale down our picture with our parameter scaleDown. This is the same as the contain, but when there is enough place to show, we do nothing about this, just show it.

The parameter none is also easy to understand, it do not stretch the size of picture, when there is not enough place to show, it will hide other part and only show the part fit the parent widget, the hide part also depends on the parameter of alignment, default it align center. Let's just look at the code.

         Container(
            color: BLUE_DEEP,
            width: 100,
            height: 100,
            child: Image.asset(
              _PIC01,
              fit: BoxFit.scaleDown,
            ),
          ),
          SizedBox(width: 10),
          Container(
            color: YELLOW,
            width: 100,
            height: 100,
            child: Image.asset(
              _PIC01,
              fit: BoxFit.none,
            ),
          ),

alignment

When we see the definition, we can see it is same of the parameter of the Container, we can use the same way as before, more detail is in the link below.

I just give the code to show the effect when we use.

 Widget _alignTopImage() => Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Container(
            color: YELLOW,
            width: 66.7,
            height: 100,
            child: Image.asset(
              _CIRCLE,
              fit: BoxFit.none,
              alignment: Alignment.topLeft,
            ),
          ),
          SizedBox(width: 10),
          Container(
            color: YELLOW,
            width: 66.7,
            height: 100,
            child: Image.asset(
              _CIRCLE,
              fit: BoxFit.none,
              alignment: Alignment.topCenter,
            ),
          ),
          SizedBox(width: 10),
          Container(
            color: YELLOW,
            width: 66.7,
            height: 100,
            child: Image.asset(
              _CIRCLE,
              fit: BoxFit.none,
              alignment: Alignment.topRight,
            ),
          ),
        ],
      );

  Widget _alignBottomImage() => Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Container(
            color: YELLOW,
            width: 66.7,
            height: 100,
            child: Image.asset(
              _CIRCLE,
              fit: BoxFit.none,
              alignment: Alignment.bottomLeft,
            ),
          ),
          SizedBox(width: 10),
          Container(
            color: YELLOW,
            width: 66.7,
            height: 100,
            child: Image.asset(
              _CIRCLE,
              fit: BoxFit.none,
              alignment: Alignment.bottomCenter,
            ),
          ),
          SizedBox(width: 10),
          Container(
            color: YELLOW,
            width: 66.7,
            height: 100,
            child: Image.asset(
              _CIRCLE,
              fit: BoxFit.none,
              alignment: Alignment.bottomRight,
            ),
          ),
        ],
      );

In the children we use them.

SizedBox(height: 20),
          Container(
            width: 200,
            height: 200,
            child: Image.asset(
              _CIRCLE,
              fit: BoxFit.none,
            ),
          ),
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text("topleft ", style: TextStyle(color: Colors.grey[700])),
              SizedBox(width: 10),
              Text("topCenter", style: TextStyle(color: Colors.grey[700])),
              SizedBox(width: 10),
              Text("topRight", style: TextStyle(color: Colors.grey[700]))
            ],
          ),
          _alignTopImage(),
          SizedBox(height: 10),
          _alignBottomImage(),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text("topleft ", style: TextStyle(color: Colors.grey[700])),
              SizedBox(width: 10),
              Text("topCenter", style: TextStyle(color: Colors.grey[700])),
              SizedBox(width: 10),
              Text("topRight", style: TextStyle(color: Colors.grey[700]))
            ],
          ),

It will show like below.

color & colorBlendMode

When we want to simply blend the picture with color, we need use them. The color is the color we want to blend and the colorBlendMode is the way of blend. Let's look at the effect.

 Widget _blendImage2() => Container(
        constraints: BoxConstraints.expand(height: 100),
        child: Row(
          children: <Widget>[
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.lighten,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.difference,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.overlay,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: YELLOW,
                    colorBlendMode: BlendMode.screen,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.srcATop,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.colorBurn,
                  ),
                )),
          ],
        ),
      );

  Widget _blendImage() => Container(
        constraints: BoxConstraints.expand(height: 100),
        child: Row(
          children: <Widget>[
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.color,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.multiply,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.darken,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: YELLOW,
                    colorBlendMode: BlendMode.luminosity,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.exclusion,
                  ),
                )),
            Expanded(
                flex: 1,
                child: Container(
                  child: Image.asset(
                    _PIC06,
                    color: PURPLE,
                    colorBlendMode: BlendMode.colorBurn,
                  ),
                )),
          ],
        ),
      );

And use these two function in the our page.

   SizedBox(height: 20),
          Container(
            width: 200,
            height: 200,
            child: Image.asset(
              _PIC06,
              fit: BoxFit.contain,
            ),
          ),
          _blendImage(),
          _blendImage2(),

repeat

This will repeat the picture when there is more place in the parent widget. The parameter is a enumin the flutter. So you use it as a type, I just use the ImageRepeat.repeatXas a example. This will repeat picture in the horizontal direction, but you should know, there must be enough place to repeat.

 Widget _repeatImage() => Container(
        constraints: BoxConstraints.expand(height: 100),
        child: Image.asset(
          _PIC03,
          repeat: ImageRepeat.repeatX,
          fit: BoxFit.contain,
        ),
      );

matchTextDirection

Sometimes, we draw the text with the TextDirection, if you want your picture draw the same way, then you can use this parameter. But you should care about that its parent widget is the Directionality, the code is below.

 Widget _directionImage() => Container(
      height: 200,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          Directionality(
            textDirection: TextDirection.ltr,
            child: Image.asset(
              _PIC04,
              matchTextDirection: true,
            ),
          ),
          Directionality(
              textDirection: TextDirection.rtl,
              child: Image.asset(_PIC04, matchTextDirection: true)),
        ],
      ));

The result is following.

filterQuality

This param controls the show quality, has these type, none,low,medium,high,the default FilterQuality.low. Let's see the using.

 Widget _qualityImage() => Container(
      height: 600,
      child: Column(
        children: <Widget>[
          Expanded(
            flex: 1,
            child: Image.asset(
              _PIC11,
              filterQuality: FilterQuality.high,
            ),
          ),
          Expanded(
            flex: 1,
            child: Image.asset(
              _PIC11,
              filterQuality: FilterQuality.none,
            ),
          ),
        ],
      ));

We can see the result, the camera icon has some saw-tooth of the FilterQuality.none value.

Other parameters

So far, we have learn many parameters,but some are not talk. I don't plan to talk about them this time, I will consider to update in the future for a higher level tutorial.

Conclusion

In this tutorial, we first talk about how to use a simple image, then talk about the parameters in the constructor.They are width&height,fit,color&colorBlendMode,repeat,matchTextDirection,filterQuality

There are so important and common using in the Image, so you must know how to use them.

Thanks for your reading!

The end.

Whole code in GitHub,star to support.

Last updated