如何在Flutter中加载NetworkImage()之前展示本地图片?

22
            new CircleAvatar(
                              backgroundColor: Colors.black87,
                              backgroundImage: new NetworkImage(url),
                              radius: 45.0,
                            )

我想在CircleAvatar中展示一张本地图片,直到从互联网完全加载NetworkImage

10个回答

22
您可以尝试使用包含在ClipOval中的FadeInImage。在网络图片加载时,FadeInImage提供了一个placeholder属性,您可以使用它来显示占位图。
注意:ClipOval如果使用过多可能会耗费更多资源,因此请谨慎使用。

如何在“NetworkImage”加载完成之前使用占位符?任何示例将不胜感激。谢谢。 - Kamlesh

16

现在有一个新的官方小部件!

首先,在项目根目录下创建一个名为assets的文件夹。

然后,在pubspec.yaml文件(也位于项目根目录中)中提到该文件夹:

flutter:
  uses-material-design: true
  assets:
    - assets/
你可以在那里放一张图片,例如将这个放置为 ./assets/loading.gif

Loading.gif

(如果你更改了 assets 文件夹中的文件,热重载将无法运行。确保完全重新启动应用程序。)

现在你可以在代码中引用加载文件了:

FadeInImage.assetNetwork(
  placeholder: 'assets/loading.gif',
  image: 'https://github.com/flutter/website/blob/master/src/_includes/code/layout/lakes/images/lake.jpg?raw=true',
);

更多详情请参见:https://flutter.io/docs/cookbook/images/fading-in-images#from-asset-bundle


3
FadeInImage不能作为CircleAvatar的图像参数传递。 - user10481267
我的小部件需要“imageProvider”。请问如何使用您的FadeInImage和网络图像解决方案来显示图像?谢谢。 - Kamlesh
我正在使用位于 https://pub.dev/packages/photo_view 的 photo_view 包。我的代码如下:PhotoView( imageProvider: NetworkImage( widget.photoPath.toString(), ),),请建议如何在网络图像加载完成之前使用占位图像。非常感谢。 - Kamlesh

14

使用 StatefulWidget,您可以向 ImageStream 添加一个 listener 并覆盖 initState,以在完全加载时触发本地图像和从互联网获取的图像之间的替换。

我使用了一张高分辨率的图片来展示加载时间:

输入图片描述

  var _loadImage = new AssetImage(
      'assets/img/basic2-090_loader_loading-512.png');
  var _myEarth = new NetworkImage(
      "http://qige87.com/data/out/73/wp-image-144183272.png");
  bool _checkLoaded = true;

  @override
  void initState() {
    _myEarth.resolve(new ImageConfiguration()).addListener((_, __) {
      if (mounted) {
        setState(() {
          _checkLoaded = false;
        });
      }
    });
  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: new Center(child: new Container(
          decoration: new BoxDecoration(shape: BoxShape.circle,),
          height: 80.0,
          width: 80.0,
          child: new CircleAvatar(
            backgroundColor: Theme
                .of(context)
                .scaffoldBackgroundColor,
            backgroundImage: _checkLoaded ? _loadImage : _myEarth,
          ),)
        )
    );
  }
}

BoxDecoration 没有宽度和高度属性。 - Nicholas Jela
这是关于 Container 组件而不是 BoxDecoration。 - Shady Aziza
这解决了我的问题,关键是我需要知道图像何时加载。 - Jaween
我应该如何显示 "CircularProgressIndicator" 而不是使用 backgroundImage _loadImage。请提供建议。谢谢。 - Kamlesh

6

你也可以使用 frameBuilder 属性。好处是,你可以在这里实现自定义的占位符 Widget。

Image.network('https://example.com/my-image',
  height: 100,
  frameBuilder: (context, child, frame, _) {
    if (frame == null) {
      // fallback to placeholder
      return MyPlaceholderWidget();
    }
    return child;
  }
)

使用Image.network是制作自己的小部件的好方法,因为FadeInImage即使图像已被缓存并且已经存在,它仍然会每次都执行动画,这很烦人。 - Noob

5

解决问题的两种方法

1) 使用Image.network:如果你想在图片加载时显示进度条、simmer或其他小部件。

  Image.network(
      "URL",
      fit: BoxFit.cover,
      loadingBuilder: (BuildContext ctx, Widget child, ImageChunkEvent loadingProgress) {
        if (loadingProgress == null) {
          return child;
        }else {
          return Center(
            child: CircularProgressIndicator(
              valueColor: AlwaysStoppedAnimation<Color>(Colors.green),
            ),
          );
        }
      },       
  )



2) 使用FadeInImage : 如果您想在加载网络图像时显示本地图像

 FadeInImage.assetNetwork( 
    image:"URL",
    placeholder:"assets/loading.png" // your assets image path
    fit: BoxFit.cover,
  )

我的小部件需要“imageProvider”。请问您有什么解决方案可以提供给我使用吗?谢谢。 - Kamlesh
我正在使用位于 https://pub.dev/packages/photo_view 的 photo_view 包。我的代码如下:PhotoView( imageProvider: NetworkImage( widget.photoPath.toString(), ),),请建议如何在网络图像加载完成之前使用占位图像。非常感谢。 - Kamlesh

3
在大型图片加载时,显示备选资源!
 new PlutoImage.networkWithPlaceholder("http://68.media.tumblr.com/f7e2e01128ca8eb2b9436aa3eb2a0a33/tumblr_ogwlnpSpcU1sikc68o1_1280.png", new Image.asset("assets/placeholder.png"));

https://github.com/FaisalAbid/pluto


3
你可以使用 FadeInImage使用 asset 中的占位图。
FadeInImage.assetNetwork(
                              placeholder: "assets/images/image1.png",
                              image:"URL"
                                ),

使用内存中的占位符

FadeInImage.memoryNetwork(
                                      placeholder: localImageBytes,
                                      image:"URL"
                                    ),

我正在使用位于 https://pub.dev/packages/photo_view 的 photo_view 软件包。我的代码如下:PhotoView( imageProvider: NetworkImage( widget.photoPath.toString(), ),),请问如何在网络图像加载之前使用占位图像?非常感谢。 - Kamlesh
@Kamlesh 请创建一个新问题。 - Abir Ahsan
1
谢谢Abir,我已经解决了这个问题,另一个stackoverflow用户分享了最好的解决方案来修复这个问题。 - Kamlesh

2
我开发了一个名为 flutter_url_image_load_fail 的软件包,用于定义加载中加载失败的小部件。"
LoadImageFromUrl(
    'https://upload.wikimedia.org/wikipedia/commons/1/17/Google-flutter-logo.png', //Image URL to load
    (image) => image, //What widget returns when the image is loaded successfully
    () => Text('Loading...'), //What widget returns when the image is loading
    (IRetryLoadImage retryLoadImage, code , message){ //What widget returns when the image failed to load
        return RaisedButton(
            child: Text('Try Again'),
            onPressed: (){
                retryLoadImage.retryLoadImage(); //Call this method to retry load the image when it failed to load
            },
        );
    },
    requestTimeout: Duration(seconds: 5) //Optionally set the timeout
)

1

使用 foregroundImageNetworkImage 作为个人资料图片,使用 backgroundImageAssetImage 作为占位符图片,像这样:

const CircleAvatar(
  radius: 60,
  backgroundColor: Colors.white,
  backgroundImage: AssetImage('assets/avatar.png'), // Placeholder
  foregroundImage: NetworkImage('https://xxx.xxx.xx.jpg'), // Profile
),

0

现在有一个新的cached_network_image包,它具有“loading”和“error”图像,以及自动图像缓存功能。 https://dev59.com/SlUL5IYBdhLWcg3wzqyZ#57493334

您可以将任何东西设置为占位符,例如从资产中使用Image.asset('assets/images/my_placeholder.png')


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接