34

I am new to Flutter. I try to load network images using image.network widget. it's working fine but sometimes it takes time to load. I added tap listener to image.network during tap I need to check image is fully loaded or not based on the result I need to redirect the page. how to check image is loaded or not?

Code:

new Image.network('http://via.placeholder.com/350x150')

Any help will be appreciated, thank you in advance

Magesh Pandian
  • 8,789
  • 12
  • 45
  • 60

5 Answers5

77

You may use the loadingBuilder which is inbuilt feature from flutter for Image.Network

I did it as below:

Image.network(imageURL,fit: BoxFit.cover,
  loadingBuilder:(BuildContext context, Widget child,ImageChunkEvent loadingProgress) {
  if (loadingProgress == null) return child;
    return Center(
      child: CircularProgressIndicator(
      value: loadingProgress.expectedTotalBytes != null ? 
             loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
             : null,
      ),
    );
  },
),
AutoM8R
  • 3,020
  • 3
  • 32
  • 52
Aditya Sharma
  • 885
  • 11
  • 15
29

for this kind of issues it's good to use the cached_network_image so you can provide a placeholder when the image is loading and an error widget in case a resource fails to load

String url = "http://via.placeholder.com/350x150";
CachedNetworkImage(
       imageUrl: url,
       placeholder: (context,url) => CircularProgressIndicator(),
       errorWidget: (context,url,error) => new Icon(Icons.error),
     ),
Jabir Ishaq
  • 177
  • 1
  • 1
  • 16
Raouf Rahiche
  • 28,948
  • 10
  • 85
  • 77
9

for ones who do not need to cache the image can use meet_network_image package,

The package basic usage :

                MeetNetworkImage(
                  imageUrl:
                      "https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg",
                  loadingBuilder: (context) => Center(
                        child: CircularProgressIndicator(),
                      ),
                  errorBuilder: (context, e) => Center(
                        child: Text('Error appear!'),
                      ),
                )

In addition, you can do that by yourself with using a FutureBuilder,

We need to get data with http call that way, we need to import http before import you also need to add pubspec.yaml and run the command flutter packages get

import 'package:http/http.dart' as http;
  FutureBuilder(
    // Paste your image URL inside the htt.get method as a parameter
    future: http.get(
        "https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg"),
    builder: (BuildContext context, AsyncSnapshot<http.Response> snapshot) {
      switch (snapshot.connectionState) {
        case ConnectionState.none:
          return Text('Press button to start.');
        case ConnectionState.active:
        case ConnectionState.waiting:
          return CircularProgressIndicator();
        case ConnectionState.done:
          if (snapshot.hasError)
            return Text('Error: ${snapshot.error}');
          // when we get the data from the http call, we give the bodyBytes to Image.memory for showing the image
          return Image.memory(snapshot.data.bodyBytes);
      }
      return null; // unreachable
    },
  );
cipli onat
  • 1,943
  • 1
  • 11
  • 26
2

This way it will start loading, then it will show the loading of the image loading and then the image. Best option if you don't want to use external libs.

Image.network(
  imgUrl,
  height: 300,
  fit: BoxFit.contain,
  frameBuilder: (_, image, loadingBuilder, __) {
    if (loadingBuilder == null) {
      return const SizedBox(
        height: 300,
        child: Center(child: CircularProgressIndicator()),
      );
    }
    return image;
  },
  loadingBuilder: (BuildContext context, Widget image, ImageChunkEvent? loadingProgress) {
    if (loadingProgress == null) return image;
    return SizedBox(
      height: 300,
      child: Center(
        child: CircularProgressIndicator(
            value: loadingProgress.expectedTotalBytes != null
                ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
                : null,
        ),
      ),
    );
  },
  errorBuilder: (_, __, ___) => Image.asset(
    AppImages.withoutPicture,
    height: 300,
    fit: BoxFit.fitHeight,
  ),
)
1

thank you for your comment thats help to resolve the situation that how to know if the image is loaded or not hope that help

I use a StatefulWidget need a editing depend on your AffichScreen

situation :

 -i have an url that i enter 
 -if url is correct affich the image if not affich an icon
 -if empty affich a Text()
 -precacheImage check if the url is correct if not give an error and change _loadingimage(bool) to false to affich the icon eror
 -i use a NetworkImage to check with precacheImage and before affich use a Image.network 



   bool _loadingimage;
ImageProvider _image;
Image _imagescreen;

@override
  void initState() {
    _loadingimage = true;
    _imageUrlfocusNode.addListener(_updateImageUrl);
    super.initState();
  }

   @override
  void dispose() {
    _imageUrlfocusNode.removeListener(_updateImageUrl);
    _quantityfocusNode.dispose();
    _imageUrlConroller.dispose();
    _imageUrlfocusNode.dispose();
    super.dispose();
  }

  void _updateImageUrl() {
    setState(() {
      _image = NetworkImage(_imageUrlConroller.text);
    });
    if (!_imageUrlfocusNode.hasFocus) {
      if (_imageUrlConroller.text.isNotEmpty) {
        setState(() {
          loadimage();
        });
      }
    }
  }

  void loadimage() {
    _loadingimage = true;
    precacheImage(_image, context, onError: (e, stackTrace) {
      // log.fine('Image ${widget.url} failed to load with error $e.');
      print('error $e');
      setState(() {
        _loadingimage = false;
        print(_loadingimage);
      });
    });
    if (_loadingimage == true) {
      _imagescreen = Image.network(
        _imageUrlConroller.text,
        fit: BoxFit.fill,
      );
    }
  }



  Container(
                              width: 100,
                              height: 100,
                              margin: EdgeInsets.only(top: 13, right: 11),
                              decoration: BoxDecoration(
                                border: Border.all(
                                  width: 1,
                                  color: Colors.grey,
                                ),
                              ),
                              child:_imageUrlConroller.text.isEmpty
                                      ? Text('enter an url')
                                      : !_loadingimage
                                          ? Container(
                                              child: Icon(Icons.add_a_photo),
                                            )
                                          : Container(
                                              child: _imagescreen,
                                            ),
                            ),
MrMoon
  • 31
  • 1
  • 6