Flutter UI Widgets

Nov 9 2021 Dart 2.14, Flutter 2.5, VS Code 1.61

Part 1: Flutter UI Widgets

4. Work with Images

Episode complete

Play next episode

Next
About this episode
See versions

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 3. Build Layouts Next episode: 5. Create Scrollable Contents

This video Work with Images was last updated on Nov 9 2021

Let’s replace the Placeholder widget with an image. Enter the following code:

...
SizedBox(
  height: 200,
  width: double.infinity,
  child: Image.network(
    imageUrl!,
    fit: BoxFit.cover,
  ),
),
...

A SizedBox is used to constraint the underlying Image to a height of 200 and a width of double.infinity. The width of double.inifinity simply tell Flutter that the child should take up the entire available width. Also, we used a SizedBox instead of a Container because we dont intend painting or positioning the widget. We just need to size the underlying child correctly.

The imageUrl is passed as the first argument of the Image.network widget. Next, the fit is set to BoxFit.cover which makes the image cover the entire widget without distorting its aspect ratio.

Note: Image.network is just one of the many constructors of Image widget. It provides a simpler api for displaying images gotten from an online source. Flutter downloads the image and caches it. Save your work.

And we have an exception. And it seems like we didnt pass the imageUrl to the CardBanner widget. Let’s do that now then save your work. And the image displays correctly.

Let’s swap the article to some other one that fills up the banner. I want to check if the styling is corrrect. Now, look closely at the top edges of the image. Notice that the Image doesnt have the rounded corners that the underlying Card widget has. To add the border radius at the top corners, we’ll be using the ClipRRect widget. This widget clips its child using a rounded rectangle.

Wrap your Image with this widget and update it like so:

ClipRRect(
  borderRadius: const BorderRadius.only(
    topLeft: Radius.circular(4),
    topRight: Radius.circular(4),
  ),
  child: SizedBox(
    height: 200,
    width: double.infinity,
    child: Image.network(
      imageUrl,
      fit: BoxFit.cover,
    ),
  ),
);

We use BorderRadius.only() constructor to specify the border radius for only the topLeft and topRight corners. The other corners would be right angled. Save your work and see the changes.

Network images can take some time to load. To display some widget while the image is downloading, the image widget provides us with the loadingBuilder property. It is a callback back function that would be called repeatedly until the image is loaded. Paste the following code:

...
loadingBuilder: (context, child, progress) {
  if (progress == null) return child;
  return const Center(child: CircularProgressIndicator());
},
...

It shows a CircularProgressIndicator by default then if the image is done downloading is shows the image. When an image is downloading, the progress value is continuosly updated and when the download is complete, the value becomes null.

Save your work. And do a hot restart to remount the widget. You can see the loading indicator is shown while the image is downloading.

Finally, let’s replace the title in the AppBar to an Image. Head over to the AppBar in main_page.dart file. Update the code to the following:

...
title: Image.asset(
  'assets/images/logo.png',
  width: 180,
),
...

This uses the Image.asset constructor here. Image.asset is used for images that are bundled with your app. Assets is simply Flutter’s way of managing resources. These could be stuffs like images, icons, fonts and any other files your app would use. The path of the asset is added and the image is given a width of 180. Save your work. If you look at the debug toolbar, you’ll notice that the debug session has broken.

This is because an exception must have occured since we haven’t configured the asset directory for our app. Android developers would store these type of files in the res/drawable folders while iOS developers would store theirs in the Images.xcasset folder. Flutter apps have only assets to store both resources, images and any other file your app would use. This code would not work yet. We need to specify the assets folder for our app.

Open up the pubspec.yaml file. This is the equivalent of a gradle build script or a podFile in Android and iOS respectively. Flutter gives you access to those types of files inside the android and iOS folder in your project. But those are for native packages that would rely solely on Android and iOS. For FLutter, you do all these type of configurations inside the pubspec.yaml file.

Add the following lines in the flutter section below:

---
assets:
  - assets/images/

This adds the images folder as an asset to our application. Note, the assets folder has been added to the project’s directory of the starter project and the logo image has been added to the images folder.

We can also specify to add only a single file but this setup adds the entire folder. Save the file. Whenever the pubspec.yaml file is updated, the pub get command runs to sync the app correctly with all its dependencies. Once that is done, do a hot restart. The exception is gone and logo displays as expected.