Check image is loaded in Image.network widget in flutter
Asked Answered
S

5

41

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

Session answered 8/6, 2018 at 11:21 Comment(4)
i think they are working on this bugAquaplane
Is any other image widget or image widget plugin available to check image loaded or not feature ?Session
You could try to use GlobalKey to get your Widget, but then you would need to get the ImageProvider.Seminary
Check this other question's answer, apparently is not so hard to implement.Stooge
D
81

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,
      ),
    );
  },
),
Deserted answered 22/9, 2019 at 11:49 Comment(2)
this should be the accepted answer, thanksTicino
Hi! thanks for your answer. It works, but it takes a long time for CircularProgressIndicator to appear. Any suggestion?Tortfeasor
A
31

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),
     ),
Aquaplane answered 8/6, 2018 at 11:52 Comment(4)
Thanks for your answer @Raouf , How to check image loaded or not programmatically in cachednetworkImage ?Session
as far as i know you can't know if image is downloaded or yet directly but if you look into the source code they provide a why to get that which is _phaseAquaplane
@RaoufRahiche thanks worked for me, but it needed a little edit, kindly accept it. thanksNatalya
small hint: if the errorWidget is not showing up, try restarting the app, a hot restart was not enough for me.Disentomb
S
10

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
    },
  );
Smithers answered 11/6, 2019 at 13:27 Comment(0)
I
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,
  ),
)
Icono answered 7/4, 2022 at 1:11 Comment(0)
S
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,
                                            ),
                            ),
Schwarzwald answered 18/2, 2020 at 17:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.