1

I'm trying to show an image placeholder while the image is being loaded from the network and replace the placeholder with an actual image with a fade-in animation. This works fine when I use a simple png image from assets. Following is the existing code:

FadeInImage(placeholder: AssetImage('assets/one.png'),
          image: NetworkImage(product.imageUrl),
          fit: BoxFit.cover,)

Now I want to load a flare animation as image placeholder. I'm using FlareActor to show flare animation but FlareActor is a widget and placeholder in FadeInImage needs ImageProvider. Is there any way to load flare animation as image placeholder and replace it to actual image with a fade-in animation.

Following is the code to load simple flare animation:

FlareActor("assets/images/image_placeholder.flr", 
               animation: "Untitled",)

Thanks

Asad
  • 81
  • 1
  • 7

2 Answers2

3

You can achieve what you want by doing like this

Stack(
      children: <Widget>[
        AnimatedOpacity(
          opacity: showImage ? 0.0: 1.0,
          child: FlareActor("assets/images/image_placeholder.flr",
            animation: "Untitled"),
        ),
        AnimatedOpacity(
          opacity : showImage ? 1.0: 0.0,
          child: Image(
            image: NetworkImage(product.imageUrl),
            fit: BoxFit.cover,
            frameBuilder: (BuildContext context, Widget child, int frame,
                bool wasSynchronouslyLoaded) {
              if (wasSynchronouslyLoaded) return child;
              if (frame != null) {
                showImage = true;
              }
              return child;
            },
          ),
        )]
  • That solution did not quite work for me. As you are changed "showImage" in frameBuilder the opacity of both widgets of Stack will not be changed because the widget does not rebuild. BTW Thanks for pointing me to right direction of using frameBuilder. I have used the stack of two widgets inside of frameBuilder to get the required result. – Asad Jul 04 '20 at 12:02
  • But we can't use setState in build function. I have tried but it was throwing an exception that "setState() or markNeedsBuild() called during build". It was creating an infinite loop. – Asad Jul 06 '20 at 18:22
1

After spending some time I was able to solve the problem with Stack and Image frameBuilder.

Following is the code:

Image.network(
          product.imageUrl,
          fit: BoxFit.cover,
          frameBuilder: (ctx, child, frame, wasSynchronouslyLoaded) {
            if (wasSynchronouslyLoaded) return child;

            return Stack(children: <Widget>[
              AnimatedOpacity(
                opacity: frame == null ? 1 : 0,
                duration: Duration(seconds: 1),
                child: frame == null
                    ? FlareActor(
                        "assets/animations/image_placeholder.flr",
                        animation: "Untitled",
                      )
                    : null,
              ),
              AnimatedOpacity(
                  opacity: frame == null ? 0 : 1,
                  duration: Duration(seconds: 1),
                  child: frame != null ? child : null),
            ]);
          },
        ),
Asad
  • 81
  • 1
  • 7