DEV Community

Cover image for How to Add  Preloader to Image in Flutter
kris for daily.dev

Posted on • Originally published at daily.dev

How to Add Preloader to Image in Flutter

Flutter is a cross-platform mobile application development framework that offers a widget-based mechanism to implement the pixel-perfect UI. Creating a state of the art apps with beautiful UI is a challenge for every mobile app developer. And, Flutter has made it easier and simple. However, with great UI comes the value of user experience as well. It is necessary to have a sustainable user experience along with a great UI. Hence, this tutorial will help learn a small aspect of optimizing the user experience by showing the loading effect (termed as pre-loaders, placeholders) before the actual data loads.

The preloaders become necessary for the user to experience the data is still loading or being fetched from the server. Until the actual data is fetched from the server and displayed on the screen, the pre-loaders will help users understand what actually is going on. The displaying of preloaders indicates that the actual data has still not loaded due to some reasons such as slow network, app errors, etc. Thus, optimizing the overall user experience. Hence, the pre-loaders are necessary for any mobile applications as well as websites. And here, we are going to learn just that on how to add image pre-loaders before the actual image loads in a Flutter app.

Create new Flutter project

First, we need to create a new Flutter project. For that, make sure that the Flutter SDK and other flutter app development related requirements are properly installed. If everything is properly set up, then in order to create a project, we can simply run the following command in the desired local directory:

flutter create imagePreloader
Enter fullscreen mode Exit fullscreen mode

After the project has been set up, we can navigate inside the project directory and execute the following command in the terminal to run the project in either an available emulator or an actual device:

flutter run
Enter fullscreen mode Exit fullscreen mode

After successfully build, we will get the following result on the emulator screen:

Alt Text

Creating Home Screen

Since we have our flutter app up and running in the emulator, we can now move to create screens. For that, we need to create a directory called ./screens inside the ./lib directory of our project. Inside the ./screens directory, we need to create a new dart file called Home.dart.

In the Home.dart, we are going to create a stateful widget to show the image as well as the preloaders. But first, we are going to show a simple App bar by returning a Scaffold widget as shown in the code snippet below:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:ui';

class HomePage extends StatefulWidget {
  HomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<HomePage> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            backgroundColor: Colors.white,
            centerTitle: true,
            title: Text(
              "Image",
              style: TextStyle(color: Colors.black87, fontFamily: 'Overpass', fontSize: 20),
            ),
            elevation: 0.0
        ),
        backgroundColor: Colors.white,
        body: Container()
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Here, we have added an App bar using AppBar widget in the Scaffold widget. The body property returns an empty Container widget.

Now, we need to import the Home.dart file in main.dart and replace the default widget with HomePage widget as shown in the code snippet below:

import 'package:flutter/material.dart';
import 'package:imagePreloader/screens/Home.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomePage(),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Hence, we will get the result as shown in the screenshot below:

Alt Text

Adding Image Container to Home Screen

Now, we are going to display an image on the Home screen. For that, we need to fetch a mock image from pexels or from anywhere. Then, we need to add the URL path of the image to a List called imagesPath.

Note that, we can directly use this URL but we are pushing the URL from imagesPath to a new List called imagesList because we want to show the Pre-loaders before the image loads on the screen.

The initializations are provided in the code snippet below:

List imagesPath = [
    "https://images.pexels.com/photos/2440061/pexels-photo-2440061.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
  ];

 List imagesList = new List();
Enter fullscreen mode Exit fullscreen mode

Now, we need to create a function to load the image URL from the imagesPath list to imagesList list. Remember that we are doing this as an alternative to fetching images from the server. Since we are not using a server to fetch the image, we have to devise the logic to load the image URL manually from the code itself.

The implementation of getImages function is provided in the code snippet below:

getImages() {
  imagesList.add(imagesPath[0]);
}
Enter fullscreen mode Exit fullscreen mode

Now, we need to call the getImages function inside the initState method:

@override
void initState() {
  super.initState();
  getImages();
}
Enter fullscreen mode Exit fullscreen mode

This initState method executes before our main build function executes once we enter the Home screen.

Now, we are going to create a image view container in the Scaffold widget body. For that, we can use the code from the following code snippet:

body: SingleChildScrollView(
        child: Padding(
          padding: EdgeInsets.symmetric(horizontal: 5, vertical: 5),
          child: Container(
            margin: EdgeInsets.only(right : 0),
            width: 500,
            height: 350,
            decoration: BoxDecoration(
              color: Colors.black26,
              borderRadius: BorderRadius.circular(16),
            ),
            child: ClipRRect(
              borderRadius: BorderRadius.circular(16),
              child: Image.network(
                  imagesList[0],
                  fit: BoxFit.cover,
              ),
            ),
          )
        )
      ),
    );
Enter fullscreen mode Exit fullscreen mode

Here, we have placed the SingleChildScrollView widget as a primary parent widget so that the whole body section is scrollable. Then, we have a Padding widget to apply some paddings which have Container as a child widget. The Container widget is configured with some unique properties which provide child widgets as a ClipRRect widget. The ChipRRect allows us to clip the edges of its child widget. As its child widget, we have used Image.network widget to display the image.

The result is displayed in the screenshot below:

Alt Text

Here, we have got an image on the screen. Now, it is time to add Pre-loaders.

Adding Shimmering Image Pre-loader

In order to add the image Pre-loader, we are going to make use of the shimmer package. This package provides an easy way to apply the shimmer effect in the Flutter app. It makes the Pre-loader implementation easy as well as optimizes the user experience.

First, we need to install the shimmer package. For that, we need to add the shimmer package to pubspec.yaml file as shown in the code snippet below:

dependencies:
  flutter:
    sdk: flutter

  shimmer: 1.1.1
Enter fullscreen mode Exit fullscreen mode

Now, we need to import the package to the Home.dart as shown in the code snippet below:

import 'package:shimmer/shimmer.dart';
Enter fullscreen mode Exit fullscreen mode

Now, we are going to implement the shimmer preloading effect using the Shimmer widget provided by the shimmer package. But first, we need to make some configurations so as to show the shimmers perfectly. So, we need to define some constants as shown in the code snippet below:

bool _loading = false;
int offset = 0;
int time = 800;
Enter fullscreen mode Exit fullscreen mode

Here, the _loading Boolean variable is for the conditional rendering of the Image and Pre-loaders. The offset and time value is configured to the Shimmer widget to set the time interval till which the pre-loaders need to load. The implementation is provided in the code snippet below:

body: (_loading)?
        Container(
          color: Colors.white,
          child: SafeArea(
            child: ListView.builder(
              padding: EdgeInsets.all(5),
              itemCount: 2,
              itemBuilder: (BuildContext context, int index) {
                offset += 5;
                time = 800 + offset;
                return Padding(
                  padding: EdgeInsets.symmetric(horizontal: 5, vertical: 5),
                  child: Shimmer.fromColors(
                    highlightColor: Colors.white,
                    baseColor: Colors.grey[500],
                    child: Container(
                      margin: EdgeInsets.only(right : 0),
                      height: 350,
                      width: 270,
                      decoration: BoxDecoration(
                        color: Colors.black26,
                        borderRadius: BorderRadius.circular(16),
                      ),
                    ),
                    period: Duration(milliseconds: time),
                  )
                );
              },
            ),
          )
        ):
         SingleChildScrollView(
          child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 5, vertical: 5),
            child: Container(
              margin: EdgeInsets.only(right : 0),
              width: 500,
              height: 350,
              decoration: BoxDecoration(
                color: Colors.black26,
                borderRadius: BorderRadius.circular(16),
              ),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(16),
                child: Image.network(
                    imagesList[0],
                    fit: BoxFit.cover,
                ),
              ),
            )
          )
        ),
    );
Enter fullscreen mode Exit fullscreen mode

Here, we show the Pre-loader template in contrast to the Image template using the _loading value as conditional rendering. We have used the Shimmer widget inside the ListView so as to show multiple loaders which can be controlled by setting the itemCount property. We have used the fromColors extension provided by the Shimmer widget with configured highlightColor and baseColor properties. We have placed a Container widget similar to Container in Image template as a child of Shimmer in order to display the shimmering effect.

Now, the above template will create a shimmering pre-loader effect. But, we still need to implement the logic to show the pre-loaders. For that, we are going to use the Timer function. The Timer function will help to delay the loading of the image onto the screen and show the pre-loaders until then. First, we need to import the package that provides the Timer function:

import 'dart:async';
Enter fullscreen mode Exit fullscreen mode

Now in getImages function, we use the Timer to delay the loading of the image and show the shimmer pre-loaders instead.

In an actual app, we fetch the data from server in which the fetching may take time. Till then, we show some loading effect which improves the overall user experience.

Since we are not pulling data from the server, we need to manually configure the delay. Hence, the implementation is provided in the code snippet below:

getImages() {
    setState(() {
      _loading = true;
    });
    Timer(Duration(seconds: 5), () => {
      imagesList.add(imagesPath[0]),
      setState(() {
        _loading = false;
      })
    });
  }
Enter fullscreen mode Exit fullscreen mode

Now, the final result with shimmering effect Pre-loaders is shown in the demo below:

Alt Text

We can notice a shimmering loading effect just before the image loads on the screen. Likewise, we can display the shimmer effect from any widget element structure of the screens as the child of the Shimmer widget uses the Flutter widgets itself. Hence, it is flexible enough to be shaped into anything.

Finally, we have implemented the image Pre-loader in a Flutter app.

Conclusion

As we talk about the importance of pre-loaders in optimizing the user experience, we can see the effect it has on the overall app UI and its usage from the demo above. It makes the overall user experience convenient. These types of pre-loaders are used in every app nowadays. So, users expect pre-loaders to happen. It creates a greater impact in terms of visual and understanding of what is going on. Pre-loaders taking a long time can interpret into problems in internet connectivity or some other type of app errors. This makes the user aware of what actually is happening. Hence, it is an important element to have knowledge of for a developer.

Now, the challenge is to create the preloaders for different widget elements. Here, we implemented the preloaders for the image element which was simple. But, the pre-loaders using the shimmer package can be shaped into anything as it uses the Flutter widgets itself as a child.

For more inspirations for beautifully designed pre-loaders, check out some amazing Flutter apps that have them integrated intuitively.


daily.dev delivers the best programming news every new tab. We will rank hundreds of qualified sources for you so that you can hack the future.
Daily Poster

Top comments (0)