【问题标题】:Check image is loaded in Image.network widget in flutter检查图像是否已加载到 Flutter 中的 Image.network 小部件中
【发布时间】:2018-11-18 10:48:58
【问题描述】:

我是 Flutter 的新手。我尝试使用image.network 小部件加载网络图像。它工作正常,但有时加载需要时间。我在点击期间将点击侦听器添加到image.network 我需要根据需要重定向页面的结果检查图像是否已完全加载。如何检查图片是否加载?

代码:

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

任何帮助将不胜感激,在此先感谢您

【问题讨论】:

  • 我认为他们正在处理这个bug
  • 是否有任何其他图像小部件或图像小部件插件可用于检查图像是否加载?
  • 您可以尝试使用GlobalKey 获取您的Widget,但随后您需要获取ImageProvider
  • Check this other question's answer,显然实现起来并不难。

标签: image flutter dart image-loading flutter-widget


【解决方案1】:

您可以使用带有占位符的FadeInImage 来做到这一点

当使用默认的图像小部件显示 图像 时,您可能会注意到它们只是在加载时弹出到屏幕上。这可能会让您的用户在视觉上感到不适。

相反,首先显示一个占位符不是很好吗,并且图像会在加载时淡入淡出?使用 FadeInImage 小部件正是为了这个目的。

FadeInImage 适用于任何类型的图像:内存中、本地资源或来自互联网的图像。

您还可以考虑使用本地资产作为占位符。首先,将资产添加到项目的pubspec.yaml 文件中(更多详细信息,请参阅Adding assets and images):

完整示例

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'Fade in images';

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Center(
          child: FadeInImage.assetNetwork(
            placeholder: 'assets/loading.gif',
            image: 'https://picsum.photos/250?image=9',
          ),
        ),
      ),
    );
  }
}

【讨论】:

    【解决方案2】:

    感谢您的评论,这有助于解决如何知道图像是否加载的情况希望帮助

    我使用 StatefulWidget 需要编辑取决于您的 AffichScreen

    情况:

     -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,
                                                ),
                                ),
    

    【讨论】:

      【解决方案3】:

      您可以使用 loadingBuilder,这是 Flutter 的内置功能,用于 Image.Network

      我是这样做的:

      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,
            ),
          );
        },
      ),
      

      【讨论】:

      • 这应该是公认的答案,谢谢
      • 嗨!感谢您的回答。它可以工作,但是 CircularProgressIndicator 需要很长时间才能出现。有什么建议吗?
      【解决方案4】:

      对于此类问题,最好使用cached_network_image 因此您可以在加载图像时提供占位符,并在资源加载失败时提供错误小部件

      String url = "http://via.placeholder.com/350x150";
      CachedNetworkImage(
             imageUrl: url,
             placeholder: (context,url) => CircularProgressIndicator(),
             errorWidget: (context,url,error) => new Icon(Icons.error),
           ),
      

      【讨论】:

      • 感谢您的回答@Raouf,如何检查是否在 cachednetworkImage 中以编程方式加载图像?
      • 据我所知,您不知道图像是下载还是直接下载,但是如果您查看源代码,它们会提供为什么要获得 _phase
      • @RaoufRahiche 感谢为我工作,但需要稍作修改,请接受。谢谢
      【解决方案5】:

      不需要缓存图片的可以使用meet_network_image包,

      包基本用法:

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

      此外,您可以使用FutureBuilder 自己完成此操作,

      我们需要这样通过http调用获取数据,我们需要在导入之前导入http你还需要添加pubspec.yaml并运行命令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
          },
        );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-30
        • 2011-02-02
        • 2020-11-14
        • 2021-08-23
        • 1970-01-01
        • 2023-03-16
        • 2011-08-29
        • 2014-11-08
        相关资源
        最近更新 更多