image - 如何让 frame Builder 和 loadingBuilder 在 Image.network 中协同工作?

标签 image flutter networking

如何让 frameBuilder 和 loadingBuilder 协同工作?

“loadingBuilder”始终有效(有或没有 frameBuilder),但“frameBuilder”仅在单独时有效(即注释掉 loadingBuilder)。

文档讨论了将 frameBuilder 与 loadingBuilder“链接”在一起,这是内部发生的事情还是我们必须考虑的事情并不明显。

Image.network(_imageUrl,
    height: 400,
    width: MediaQuery.of(context).size.width,
    fit: BoxFit.fitWidth,

    frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) {
        if (wasSynchronouslyLoaded) return child;
        return AnimatedOpacity(
                opacity: frame == null ? 0 : 1,
                duration: Duration(seconds: 5),
                curve: Curves.easeOut,
                child: child,
            );
    },

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

    errorBuilder: (BuildContext context, Object exception, StackTrace stackTrace) {
        return Text('Failed to load image');
    },
),

编辑:

到底发生了什么:

情况 1:当 loadingBuilder 为 ALONE 时,CircularProgressIndicator 正在显示并且加载过程已完成,然后指示器消失并且加载的图像正在显示而不褪色。 (完美)

情况 2:当 frameBuilder 是 ALONE 时,图像需要时间加载(当然有指示器),然后加载的图像按预期逐渐显示。 (完美)

情况 3:当同时启用 frameBuilder 和 loadingBuilder 时,发生的情况与情况 1 完全相同,图像没有任何褪色。 (错误)

预期行为:

指示器在加载过程中显示,然后消失,图像以渐变效果显示。

我需要修复此代码并找出问题出在哪里。

最佳答案

似乎“链接”是自动发生的,但您仍然需要考虑它们链接在一起的结果。

它们不能协同工作的问题是因为当frame == null时,显示了CircularProgressIndicator; AnimatedOpacity 仅在 frame 不为 null 时显示,因此它的不透明度始终为 1,这意味着我们失去了淡出效果。

解决方法是加载时opticity设置为0,加载时opticity设置为1。

下面的代码应该可以工作:

/// Flutter code sample for Image.frameBuilder

// The following sample demonstrates how to use this builder to implement an
// image that fades in once it's been loaded.
//
// This sample contains a limited subset of the functionality that the
// [FadeInImage] widget provides out of the box.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

/// This is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

bool loading = false;

/// This is the stateless widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

  @override
  MyStatefulWigdetState createState() => MyStatefulWigdetState();
}

class MyStatefulWigdetState extends State<MyStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border.all(),
        borderRadius: BorderRadius.circular(20),
      ),
      child: Image.network(
        'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg',
        frameBuilder: (BuildContext context, Widget child, int frame,
            bool wasSynchronouslyLoaded) {
          if (wasSynchronouslyLoaded) {
            return child;
          }
          return AnimatedOpacity(
            child: child,
            opacity: loading ? 0 : 1,
            duration: const Duration(seconds: 3),
            curve: Curves.easeOut,
          );
        },
        loadingBuilder: (BuildContext context, Widget child,
            ImageChunkEvent loadingProgress) {
          if (loadingProgress == null) {
            // The child (AnimatedOpacity) is build with loading == true, and then the setState will change loading to false, which trigger the animation
            WidgetsBinding.instance.addPostFrameCallback((_) {
              setState(() => loading = false);
            });

            return child;
          }
          loading = true;
          return Center(
            child: CircularProgressIndicator(
              value: loadingProgress.expectedTotalBytes != null
                  ? loadingProgress.cumulativeBytesLoaded /
                      loadingProgress.expectedTotalBytes
                  : null,
            ),
          );
        },
      ),
    );
  }
}

关于image - 如何让 frame Builder 和 loadingBuilder 在 Image.network 中协同工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64412981/

相关文章:

firebase - Dart 未处理异常 : type 'List<dynamic>' is not a subtype of type 'Iterable<Map<dynamic, dynamic>>' in type cast

flutter - 如何在flutter中访问有状态小部件中的类变量?

dart - 如何即时显示版本号

python - 使用套接字锁定另一台计算机而不中断连接

python - 使用Python通过套接字(端口80)连接基本访问webdata(html)

java - fragment 无法显示图像

jquery - 调整图像大小

javascript - 使用Jquery获取图像的位置

c# - 在 ASP.NET 中创建文件夹并将图像上传到该文件夹​​的最佳方法?

php - Apache/PHP 多请求处理和调度?