Flutter (18): Pictures and Icons

Time: Column:Mobile & Frontend views:235

18.1 Images

In Flutter, we can use the Image widget to load and display images. The image source can be from assets, files, memory, or the internet.

1. ImageProvider

ImageProvider is an abstract class that defines the interface load() for obtaining image data. Different data sources require different implementations of ImageProvider. For instance, AssetImage is an ImageProvider that loads images from assets, while NetworkImage is used to load images from the internet.

2. Image

The Image widget has a required image parameter, which corresponds to an ImageProvider. Below are examples of loading images from assets and the internet.

1) Loading an image from assets

First, create an images directory in the root of the project and copy the image avatar.png into it.

Then, add the following content under the flutter section of the pubspec.yaml file:

  assets:
    - images/avatar.png

Note: Since YAML files are sensitive to indentation, you must ensure that every level is indented with two spaces. In this case, assets should be preceded by two spaces.

Now, you can load the image with:

Image(
  image: AssetImage("images/avatar.png"),
  width: 100.0,
);

The Image widget also provides a shortcut constructor Image.asset for loading images from assets:

Image.asset("images/avatar.png",
  width: 100.0,
)
2) Loading an image from the internet

NetworkImage can be used to load an image from the internet, for example:

Image(
  image: NetworkImage(
      "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4"),
  width: 100.0,
)

Similarly, Image.network provides a shortcut constructor for loading images from the web:

Image.network(
  "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4",
  width: 100.0,
)

When these two examples are executed, the images will load successfully, as shown in Figure 3.

Flutter (18): Pictures and Icons


3) Parameters

The Image widget defines several parameters that control the appearance, size, and blend mode of the image. Let’s explore the main parameters of the Image widget:

const Image({
  ...
  this.width, // Image width
  this.height, // Image height
  this.color, // Color to blend with the image
  this.colorBlendMode, // Blending mode
  this.fit, // Scaling mode
  this.alignment = Alignment.center, // Alignment
  this.repeat = ImageRepeat.noRepeat, // Repeat mode
  ...
})
  • width, height: Used to set the width and height of the image. If not specified, the image will be displayed at its original size as much as possible, constrained by the parent container. If only one of width or height is set, the other dimension will scale proportionally. This behavior can be adjusted using the fit property.

  • fit: This property defines how the image should be scaled to fit within its display area if the display size is different from the image's natural size. The possible values are defined in BoxFit, which is an enum:

    • fill: Stretches the image to fill the display area, changing the aspect ratio (causing distortion).

    • cover: Scales the image to maintain its aspect ratio while filling the display area. The excess parts are cropped.

    • contain: This is the default value. Scales the image to fit within the display area without changing its aspect ratio (no distortion).

    • fitWidth: Scales the image to match the width of the display area while maintaining its aspect ratio. The height is scaled accordingly.

    • fitHeight: Scales the image to match the height of the display area while maintaining its aspect ratio. The width is scaled accordingly.

    • none: No scaling is applied. If the image is larger than the display area, only the center portion is displayed.

A picture is worth a thousand words! Different fit values applied to a square avatar image produce results like those shown in Figure .

Flutter (18): Pictures and Icons

  • color and colorBlendMode: These properties allow color blending during image rendering. color specifies the blend color, and colorBlendMode defines the blending mode. Here's a simple example:

Image(
  image: AssetImage("images/avatar.png"),
  width: 100.0,
  color: Colors.blue,
  colorBlendMode: BlendMode.difference,
);

The result is shown in Figure  (colored image).

Flutter (18): Pictures and Icons

  • repeat: Specifies how the image should repeat when its size is smaller than the display area. Here's a simple example:

Image(
  image: AssetImage("images/avatar.png"),
  width: 100.0,
  height: 200.0,
  repeat: ImageRepeat.repeatY ,
)

The result is shown in Figure .

Flutter (18): Pictures and Icons

Here’s a complete example:

import 'package:flutter/material.dart';

class ImageAndIconRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var img = AssetImage("images/avatar.png");
    return SingleChildScrollView(
      child: Column(
        children: <Image>[
          Image(image: img, height: 50.0, width: 100.0, fit: BoxFit.fill),
          Image(image: img, height: 50.0, width: 50.0, fit: BoxFit.contain),
          Image(image: img, width: 100.0, height: 50.0, fit: BoxFit.cover),
          Image(image: img, width: 100.0, height: 50.0, fit: BoxFit.fitWidth),
          Image(image: img, width: 100.0, height: 50.0, fit: BoxFit.fitHeight),
          Image(image: img, width: 100.0, height: 50.0, fit: BoxFit.scaleDown),
          Image(image: img, height: 50.0, width: 100.0, fit: BoxFit.none),
          Image(
            image: img,
            width: 100.0,
            color: Colors.blue,
            colorBlendMode: BlendMode.difference,
            fit: BoxFit.fill,
          ),
          Image(
            image: img,
            width: 100.0,
            height: 200.0,
            repeat: ImageRepeat.repeatY,
          )
        ].map((e) {
          return Row(
            children: <Widget>[
              Padding(
                padding: EdgeInsets.all(16.0),
                child: SizedBox(width: 100, child: e),
              ),
              Text(e.fit.toString())
            ],
          );
        }).toList(),
      ),
    );
  }
}

3. Image Caching

Flutter automatically caches images in memory after loading them. More details about Image and its internals will be covered in the advanced sections.


18.2 Icons

In Flutter, you can use icon fonts, similar to how they are used in web development. An icon font is essentially a font file where each character represents a specific glyph, and in the case of icon fonts, these glyphs are icons.

Icon fonts have several advantages over images in Flutter development:

  • Smaller size: Reduces the size of the app package.

  • Vector-based: Icon fonts are vector images, so they remain sharp when scaled up.

  • Can apply text styles: You can change the color, size, and alignment of icon fonts, just like text.

  • Mixed with text: Icon fonts can be used alongside text via TextSpan.

1. Using Material Design Icon Fonts

Flutter includes a set of Material Design icon fonts by default, which can be enabled by adding the following to the pubspec.yaml file:

flutter:
  uses-material-design: true

You can browse all Material Design icons on their official website.

Here's a simple example:

String icons = "";
// accessible: 0xe03e
icons += "uE03e";
// error: 0xe237
icons += " uE237";
// fingerprint: 0xe287
icons += " uE287";

Text(
  icons,
  style: TextStyle(
    fontFamily: "MaterialIcons",
    fontSize: 24.0,
    color: Colors.green,
  ),
);

The result is shown in Figure .

Flutter (18): Pictures and Icons

Instead of manually specifying each icon’s code point, Flutter provides the IconData and Icon classes to display icon fonts. The above example can be rewritten as:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Icon(Icons.accessible, color: Colors.green),
    Icon(Icons.error, color: Colors.green),
    Icon(Icons.fingerprint, color: Colors.green),
  ],
)

The Icons class contains static variables representing all Material Design icons.

2. Using Custom Icon Fonts

You can also use custom icon fonts. Websites like iconfont.cn offer a variety of icon fonts that you can download and use in your project.

To use a custom icon font, for example, for a book icon and a WeChat icon, follow these steps:

  1. Import the icon font file. This process is the same as importing regular fonts. Assuming the font file is located in the project root directory at "fonts/iconfont.ttf", add the following to the pubspec.yaml file:

fonts:
  - family: myIcon  # Specify a font family name
    fonts:
      - asset: fonts/iconfont.ttf
  1. Define a class MyIcons that maps the custom icons from the font file to static variables, similar to how the Icons class works:

class MyIcons {
  // Book icon
  static const IconData book = const IconData(
      0xe614, 
      fontFamily: 'myIcon', 
      matchTextDirection: true);
  
  // WeChat icon
  static const IconData wechat = const IconData(
      0xec7d, 
      fontFamily: 'myIcon', 
      matchTextDirection: true);
}
  1. Use the custom icons:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Icon(MyIcons.book, color: Colors.purple),
    Icon(MyIcons.wechat, color: Colors.green),
  ],
)

The result is shown in Figure .

Flutter (18): Pictures and Icons